Page MenuHomeFreeBSD

D18908.id53046.diff
No OneTemporary

D18908.id53046.diff

Index: lib/libfetch/common.h
===================================================================
--- lib/libfetch/common.h
+++ lib/libfetch/common.h
@@ -76,6 +76,9 @@
void fetch_seterr(struct fetcherr *, int);
void fetch_syserr(void);
void fetch_info(const char *, ...) __printflike(1, 2);
+int fetch_socks5_getenv(char **host, int *port);
+int fetch_socks5_init(conn_t *conn, const char *host,
+ int port, int verbose);
int fetch_default_port(const char *);
int fetch_default_proxy_port(const char *);
struct addrinfo *fetch_resolve(const char *, int, int);
Index: lib/libfetch/common.c
===================================================================
--- lib/libfetch/common.c
+++ lib/libfetch/common.c
@@ -42,6 +42,7 @@
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
#include <netdb.h>
#include <poll.h>
#include <pwd.h>
@@ -314,7 +315,6 @@
}
-
/*
* Bind a socket to a specific local address
*/
@@ -336,6 +336,190 @@
}
+/*
+ * SOCKS5 connection initiation, based on RFC 1928
+ * Default DNS resolution over SOCKS5
+ */
+int
+fetch_socks5_init(conn_t *conn, const char *host, int port, int verbose)
+{
+ /*
+ * Size is based on largest packet prefix (4 bytes) +
+ * Largest FQDN (256) + one byte size (1) +
+ * Port (2)
+ */
+ unsigned char buf[263];
+ unsigned char *ptr;
+
+ if (verbose)
+ fetch_info("Initializing SOCKS5 connection: %s:%d", host, port);
+
+ /* Connection initialization */
+ ptr = buf;
+ *ptr++ = 0x05;
+ *ptr++ = 0x01;
+ *ptr++ = 0x00;
+
+ if (fetch_write(conn, buf, 3) != 3) {
+ fprintf(stderr, "SOCKS5: Failed to send selection method.\n");
+ goto fail;
+ }
+
+ /* Verify response from SOCKS5 server */
+ if (fetch_read(conn, buf, 2) != 2) {
+ fprintf(stderr, "SOCKS5: Failed to read method.\n");
+ goto fail;
+ }
+
+ ptr = buf;
+ if (ptr[0] != 0x05) {
+ fprintf(stderr, "SOCKS5: Currently only version 5 is implemented.\n");
+ goto fail;
+ }
+ if (ptr[1] == 0xFF) {
+ fprintf(stderr, "SOCKS5: No acceptable methods. Disconnecting.\n");
+ goto fail;
+ }
+ else if (ptr[1] != 0x00) {
+ fprintf(stderr, "SOCKS5: Method currently not implemented. Disconnecting.\n");
+ goto fail;
+ }
+
+ /* Send Request */
+ ptr = buf;
+ *ptr++ = 0x05;
+ *ptr++ = 0x01;
+ *ptr++ = 0x00;
+ /* Encode all targets as a hostname to avoid DNS leaks */
+ *ptr++ = 0x03;
+ *ptr++ = strlen(host);
+ strncpy(ptr, host, strlen(host));
+ ptr = ptr + strlen(host);
+
+ port = htons(port);
+ *ptr++ = port & 0x00ff;
+ *ptr++ = (port & 0xff00) >> 8;
+
+ if (fetch_write(conn, buf, ptr - buf) != ptr - buf) {
+ fprintf(stderr, "SOCKS5: Failed to request.\n");
+ goto fail;
+ }
+
+ /* BND.ADDR is variable length, read the largest on non-blocking socket */
+ if (!fetch_read(conn, buf, 263)) {
+ fprintf(stderr, "SOCKS5: Failed to receive reply.\n");
+ goto fail;
+ }
+
+ ptr = buf;
+ if (*ptr++ != 0x05) {
+ fprintf(stderr, "SOCKS5: Server responded with a non-version 5 response.\n");
+ goto fail;
+ }
+
+ switch(*ptr++) {
+ case 0x00:
+ break;
+ case 0x01:
+ fprintf(stderr, "SOCKS5: General server failure\n");
+ goto fail;
+ break;
+ case 0x02:
+ fprintf(stderr, "SOCKS5: Connection not allowed by ruleset.\n");
+ goto fail;
+ break;
+ case 0x03:
+ fprintf(stderr, "SOCKS5: Network unreachable.\n");
+ goto fail;
+ break;
+ case 0x04:
+ fprintf(stderr, "SOCKS5: Host unreachable.\n");
+ goto fail;
+ break;
+ case 0x05:
+ fprintf(stderr, "SOCKS5: Connection refused.\n");
+ goto fail;
+ break;
+ case 0x06:
+ fprintf(stderr, "SOCKS5: TTL expired.\n");
+ goto fail;
+ break;
+ case 0x07:
+ fprintf(stderr, "SOCKS5: Command not supported.\n");
+ goto fail;
+ break;
+ case 0x08:
+ fprintf(stderr, "SOCKS: Address type not supported.\n");
+ goto fail;
+ break;
+ default:
+ fprintf(stderr, "SOCKS5: Unspecified failure.\n");
+ goto fail;
+ break;
+ }
+
+ return (1);
+
+fail:
+ return (0);
+}
+
+/*
+ * Perform SOCKS5 initialization
+ */
+int
+fetch_socks5_getenv(char **host, int *port)
+{
+ char *socks5env, *endptr, *ext;
+
+ if (!(socks5env = getenv("SOCKS5_PROXY")) || !*socks5env) {
+ *host = NULL;
+ *port = -1;
+ return (1);
+ }
+
+ /* IPv6 addresses begin and end in brackets */
+ if (socks5env[0] == '[') {
+ if (socks5env[strlen(socks5env)-1] == ']') {
+ *host = strndup(socks5env, strlen(socks5env));
+ *port = 1080; /* Default port as defined in RFC1928 */
+ }
+ else {
+ ext = strstr(socks5env, "]:");
+ if (!ext) {
+ fprintf(stderr, "Bad SOCKS5_PROXY format, missing closing ']': %s\n",
+ socks5env);
+ return (0);
+ }
+ ext=ext+1;
+ *host = strndup(socks5env, (ext)-(socks5env));
+ *port = strtoimax(ext+1, (char **)&endptr, 10);
+ if (*port == 0 && errno == EINVAL) {
+ fprintf(stderr, "Bad SOCKS5_PROXY port: %s\n", socks5env);
+ return (0);
+ }
+ }
+ }
+ else {
+ ext = strrchr(socks5env, ':');
+ if (!ext) {
+ *host = strdup(socks5env);
+ *port = 1080;
+ }
+ else {
+ *host = strndup(socks5env, ext-socks5env);
+ *port = strtoimax(ext+1, (char **)&endptr, 10);
+ if (*port == 0 && errno == EINVAL) {
+ fprintf(stderr, "Bad SOCKS5_PROXY port: %s\n", socks5env);
+ return (0);
+ }
+ }
+ }
+
+ return (2);
+}
+
+
/*
* Establish a TCP connection to the specified port on the specified host.
*/
@@ -344,24 +528,41 @@
{
struct addrinfo *cais = NULL, *sais = NULL, *cai, *sai;
const char *bindaddr;
+ char *sockshost;
+ int socksport;
conn_t *conn = NULL;
int err = 0, sd = -1;
DEBUGF("---> %s:%d\n", host, port);
- /* resolve server address */
- if (verbose)
- fetch_info("resolving server address: %s:%d", host, port);
- if ((sais = fetch_resolve(host, port, af)) == NULL)
+ /* Check if SOCKS5_PROXY env variable is set */
+ if(!fetch_socks5_getenv(&sockshost, &socksport))
goto fail;
- /* resolve client address */
- bindaddr = getenv("FETCH_BIND_ADDRESS");
- if (bindaddr != NULL && *bindaddr != '\0') {
+ /* Not using SOCKS5 proxy */
+ if (!sockshost) {
+ /* resolve server address */
+ if (verbose)
+ fetch_info("resolving server address: %s:%d", host, port);
+ if ((sais = fetch_resolve(host, port, af)) == NULL)
+ goto fail;
+
+ /* resolve client address */
+ bindaddr = getenv("FETCH_BIND_ADDRESS");
+ if (bindaddr != NULL && *bindaddr != '\0') {
+ if (verbose)
+ fetch_info("resolving client address: %s", bindaddr);
+ if ((cais = fetch_resolve(bindaddr, 0, af)) == NULL)
+ goto fail;
+ }
+ }
+ else {
+ /* resolve socks5 proxy address */
if (verbose)
- fetch_info("resolving client address: %s", bindaddr);
- if ((cais = fetch_resolve(bindaddr, 0, af)) == NULL)
+ fetch_info("resolving SOCKS5 server address: %s:%d", sockshost, socksport);
+ if ((sais = fetch_resolve(sockshost, socksport, af)) == NULL) {
goto fail;
+ }
}
/* try each server address in turn */
@@ -389,13 +590,20 @@
sd = -1;
}
if (err != 0) {
- if (verbose)
+ if (verbose && !sockshost)
fetch_info("failed to connect to %s:%d", host, port);
+ else if (verbose && sockshost)
+ fetch_info("failed to connect to SOCKS5 server %s:%d", sockshost, socksport);
goto syserr;
}
+
if ((conn = fetch_reopen(sd)) == NULL)
goto syserr;
+
+ if (sockshost)
+ if (!fetch_socks5_init(conn, host, port, verbose))
+ goto fail;
if (cais != NULL)
freeaddrinfo(cais);
if (sais != NULL)
Index: lib/libfetch/fetch.3
===================================================================
--- lib/libfetch/fetch.3
+++ lib/libfetch/fetch.3
@@ -652,6 +652,12 @@
Same as
.Ev NO_PROXY ,
for compatibility.
+.It Ev SOCKS5_PROXY
+Uses SOCKS version 5 to make connection. The format must be
+the IP or hostname followed by a colon for the port. IPv6
+addresses must enclose the address in brackets. If not port
+is specified, the default is 1080. This setting will supercede
+a connection to an HTTP_PROXY.
.It Ev SSL_ALLOW_SSL3
Allow SSL version 3 when negotiating the connection (not recommended).
.It Ev SSL_CA_CERT_FILE
@@ -710,6 +716,17 @@
NO_PROXY=localhost,127.0.0.1
.Ed
.Pp
+To use a SOCKS5 proxy, set the SOCKS5_PROXY environment variable to a
+valid host or IP followed by an optional colon and the port. IPv6 addresses
+must be enclosed in brackets. The following are examples of valid settings:
+.Pp
+.Dl SOCKS5_PROXY=proxy.example.com
+.Dl SOCKS5_PROXY=proxy.example.com:1080
+.Dl SOCKS5_PROXY=192.0.2.0
+.Dl SOCKS5_PROXY=198.51.100.0:1080
+.Dl SOCKS5_PROXY=[2001:db8::1]
+.Dl SOCKS5_PROXY=[2001:db8::2]:1080
+.Pp
Access HTTPS website without any certificate verification whatsoever:
.Bd -literal -offset indent
SSL_NO_VERIFY_PEER=1

File Metadata

Mime Type
text/plain
Expires
Sun, Aug 23, 11:16 AM (4 m, 39 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37077826
Default Alt Text
D18908.id53046.diff (8 KB)

Event Timeline