diff --git a/util.c b/util.c index 6c5d9c00..558b42b5 100644 --- a/util.c +++ b/util.c @@ -1783,6 +1783,63 @@ static bool http_negotiate(struct pool *pool, int sockd, bool http0) return true; } +static bool socks5_negotiate(struct pool *pool, int sockd) +{ + unsigned char atyp, uclen; + unsigned short port; + char buf[515]; + int i, len; + + buf[0] = 0x05; + buf[1] = 0x01; + buf[2] = 0x00; + send(sockd, buf, 3, 0); + if (recv_byte(sockd) != 0x05 || recv_byte(sockd) != buf[2]) { + applog(LOG_WARNING, "Bad response from %s:%s SOCKS5 server", + pool->sockaddr_proxy_url, pool->sockaddr_proxy_port ); + return false; + } + + buf[0] = 0x05; + buf[1] = 0x01; + buf[2] = 0x00; + buf[3] = 0x03; + len = (strlen(pool->sockaddr_url)); + if (len > 255) + len = 255; + uclen = len; + buf[4] = (uclen & 0xff); + memcpy(buf + 5, pool->sockaddr_url, len); + port = atoi(pool->stratum_port); + buf[5 + len] = (port >> 8); + buf[6 + len] = (port & 0xff); + send(sockd, buf, (7 + len), 0); + if (recv_byte(sockd) != 0x05 || recv_byte(sockd) != 0x00) { + applog(LOG_WARNING, "Bad response from %s:%s SOCKS5 server", + pool->sockaddr_proxy_url, pool->sockaddr_proxy_port ); + return false; + } + + recv_byte(sockd); + atyp = recv_byte(sockd); + if (atyp == 0x01) { + for (i = 0; i < 4; i++) + recv_byte(sockd); + } else if (atyp == 0x03) { + len = recv_byte(sockd); + for (i = 0; i < len; i++) + recv_byte(sockd); + } else { + applog(LOG_WARNING, "Bad response from %s:%s SOCKS5 server", + pool->sockaddr_proxy_url, pool->sockaddr_proxy_port ); + return false; + } + for (i = 0; i < 2; i++) + recv_byte(sockd); + + return true; +} + static bool setup_stratum_socket(struct pool *pool) { struct addrinfo servinfobase, *servinfo, *hints, pbase, *p; @@ -1854,6 +1911,10 @@ static bool setup_stratum_socket(struct pool *pool) if (!http_negotiate(pool, sockd, false)) return false; break; + case CURLPROXY_SOCKS5: + if (!socks5_negotiate(pool, sockd)) + return false; + break; default: applog(LOG_WARNING, "Unsupported proxy type for %s:%s", pool->sockaddr_proxy_url, pool->sockaddr_proxy_port);