Oh, hello and good evening, for auld lang syne!
Steffen Nurpmeso wrote in <20190911141510.7s2dr%[email protected]>:
|please excuse the late reply.
Terrible! I apologise for the silence.
...
Thomas Dickey wrote in <20190907195941.c2gqjhnuj2pp44az@prl-debianold-64\
.jexium-island.net>:
|On Sat, Sep 07, 2019 at 08:51:26PM +0200, Steffen Nurpmeso wrote:
|> I was forced to use lynx via SOCKS5 proxy, which i never did
|> before. To my surprise that did not work, it needs an additional
|> library. That increased the surprise, because all one needs for
|> SOCKS5 support, even including the DNS lookup, is to hook
|> connect(2) -- that is how i did it, as easy as [1]. And in fact
|
|That's changed over time - there's no standard/portable implementation
|of socks5, and (the last time I looked...) none of the extent versions
|corresponded to what lynx worked with long ago :-)
|
|> i became inspired by Gaetan Bisson's usocks-06.c, which can be
|> used via $LD_PRELOAD, and which got me going. I will attach it.
|>
|> Wouldn't it be much nicer if there would be a -socks=[HOST]:PORT
|> command line argument and a simple, always compiled in, wrapper
|> around connect, just the way i do it (in [1])?
|
|that's a thought...
...
Thomas Dickey wrote in <20190910092328.5aevtmukues22322@prl-debianold-64\
.jexium-island.net>:
|On Mon, Sep 09, 2019 at 03:43:59PM +0200, Steffen Nurpmeso wrote:
|> Thomas Dickey wrote in <20190908105750.qc3ut2e3rkrswfm4@prl-debianold-64\
|> .jexium-island.net>:
|...
|>|If you have something that works reasonably well on one of the BSDs,
|>|making it more portable (adding configure checks, command-line options,
|>|etc.) is fairly routine.
|>
|> That is BSD socket code + read(2) + write(2).
|> I will throw an eye as soon as possible, and report back then, ok?
|
|sounds good
Right. So here is a working patch, porting over my own SOCKS5
code with slight adjustments for lynx. It took hours to realize
that PARSE_HOST requires a protocol prefix, _what_a_mess_. Note
the diff was finally produced on v2-8-9rel_1, i tried several tags
from v2-9-0dev_4a downwards, but could not get something
compilable. (But git cherry-pick'ing the patch worked.)
I hope you like it, it works fine for me here?
Ciao, and a nice Sunday i wish from Germany!
--steffen
|
|Der Kragenbaer, The moon bear,
|der holt sich munter he cheerfully and one by one
|einen nach dem anderen runter wa.ks himself off
|(By Robert Gernhardt)
diff --git a/WWW/Library/Implementation/HTTCP.c b/WWW/Library/Implementation/HTTCP.c
index 4669efd4..75f3a161 100644
--- a/WWW/Library/Implementation/HTTCP.c
+++ b/WWW/Library/Implementation/HTTCP.c
@@ -1825,6 +1825,10 @@ int HTDoConnect(const char *url,
int default_port,
int *s)
{
+ /* On error goto jout */
+ char *socks5_host;
+ int socks5_host_len, socks5_port;
+ const char *socks5_orig_url;
int status = 0;
char *line = NULL;
char *p1 = NULL;
@@ -1836,7 +1840,45 @@ int HTDoConnect(const char *url,
#else
struct sockaddr_in sock_A;
struct sockaddr_in *soc_in = &sock_A;
+#endif
+
+ /* In case of a present SOCKS5 proxy, marshal */
+ if((socks5_orig_url = socks5_proxy) != NULL){
+ size_t i;
+ int xport;
+
+ xport = default_port;
+ socks5_orig_url = url;
+
+ /* Get node name and optional port number of wanted URL */
+ p1 = HTParse(url, "", PARSE_HOST);
+ socks5_host = NULL;
+ StrAllocCopy(socks5_host, p1);
+ strip_userid(socks5_host, FALSE);
+ FREE(p1);
+
+ if((i = strlen(socks5_host)) > 255){
+ HTAlert(gettext("SOCKS5: hostname too long."));
+ goto jout;
+ }
+ socks5_host_len = (int)i;
+
+ if(HTParsePort((char*)url, &socks5_port) == NULL)
+ socks5_port = xport;
+
+ /* And switch over to our SOCKS5 config; in order to embed that into
+ * lynx environment, prepend protocol prefix */
+ default_port = 1080; /* RFC 1928 */
+ HTSACat(&p1, "socks://");
+ HTSACat(&p1, socks5_proxy);
+ url = p1;
+ p1 = NULL;
+
+ protocol = HTSprintf0(NULL, gettext("(for %s at %s) SOCKS5"),
+ protocol, socks5_host);
+ }
+#ifndef INET6
/*
* Set up defaults.
*/
@@ -1859,11 +1901,10 @@ int HTDoConnect(const char *url,
/* HTParseInet() is useless! */
res0 = HTGetAddrInfo(host, default_port);
if (res0 == NULL) {
- HTSprintf0(&line, gettext("Unable to locate remote host %s."), host);
- _HTProgress(line);
- FREE(host);
- FREE(line);
- return HT_NO_DATA;
+ HTSprintf0(&line, gettext("Unable to locate remote host %s."), host);
+ _HTProgress(line);
+ status = HT_NO_DATA;
+ goto jout;
}
#else
status = HTParseInet(soc_in, host);
@@ -1882,16 +1923,12 @@ int HTDoConnect(const char *url,
}
status = HT_NO_DATA;
}
- FREE(host);
- FREE(line);
- return status;
+ goto jout;
}
#endif /* INET6 */
HTSprintf0(&line, gettext("Making %s connection to %s"), protocol, host);
_HTProgress(line);
- FREE(host);
- FREE(line);
/*
* Now, let's get a socket set up from the server for the data.
@@ -1900,7 +1937,8 @@ int HTDoConnect(const char *url,
*s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (*s == -1) {
HTAlert(gettext("socket failed."));
- return HT_NO_DATA;
+ status = HT_NO_DATA;
+ goto jout;
}
#else
for (res = res0; res; res = res->ai_next) {
@@ -1916,7 +1954,6 @@ int HTDoConnect(const char *url,
gettext("socket failed: family %d addr %s port %s."),
res->ai_family, hostbuf, portbuf);
_HTProgress(line);
- FREE(line);
continue;
}
#endif /* INET6 */
@@ -2005,13 +2042,13 @@ int HTDoConnect(const char *url,
if ((tries++ / TRIES_PER_SECOND) >= connect_timeout) {
HTAlert(gettext("Connection failed (too many retries)."));
#ifdef INET6
- FREE(line);
#ifndef NSL_FORK
if (res0)
freeaddrinfo(res0);
#endif
#endif /* INET6 */
- return HT_NO_DATA;
+ status = HT_NO_DATA;
+ goto jout;
}
set_timeout(&select_timeout);
FD_ZERO(&writefds);
@@ -2204,7 +2241,6 @@ int HTDoConnect(const char *url,
#endif /* !DOSPATH || __DJGPP__ */
#ifdef INET6
- FREE(line);
#ifdef NSL_FORK
FREE_NSL_FORK(res0);
#else
@@ -2212,6 +2248,109 @@ int HTDoConnect(const char *url,
freeaddrinfo(res0);
#endif
#endif /* INET6 */
+
+ /* Now if this was a SOCKS5 proxy connection, go for the real one */
+ if(status >= 0 && socks5_orig_url != NULL){
+ unsigned char pbuf[4 + 1 + 255 + 2];
+ size_t i;
+ char const *emsg;
+
+ /* RFC 1928: version identifier/method selection message */
+ pbuf[0] = 0x05; /* VER: protocol version: X'05' */
+ pbuf[1] = 0x01; /* NMETHODS: 1 */
+ pbuf[2] = 0x00; /* METHOD: X'00' NO AUTHENTICATION REQUIRED */
+ if(write(*s, pbuf, 3) != 3){
+jerrsocks:
+ HTAlert(LYStrerror(errno));
+jesocks:
+ NETCLOSE(*s);
+ status = HT_NO_CONNECTION;
+ goto jout;
+ }
+
+ /* Receive greeting */
+ if(HTDoRead(*s, pbuf, 2) != 2)
+ goto jerrsocks;
+ if(pbuf[0] != 0x05 || pbuf[1] != 0x00){
+jesocksreply:
+ emsg = N_("unexpected reply\n");
+jesocksreplymsg:
+ HTAlert(gettext(emsg));
+ goto jesocks;
+ }
+
+ /* RFC 1928: CONNECT request */
+ HTSprintf0(&line, gettext("SOCKS5: connecting to %s"), socks5_host);
+ _HTProgress(line);
+ pbuf[0] = 0x05; /* VER: protocol version: X'05' */
+ pbuf[1] = 0x01; /* CMD: CONNECT X'01' */
+ pbuf[2] = 0x00; /* RESERVED */
+ pbuf[3] = 0x03; /* ATYP: domain name */
+ pbuf[4] = (unsigned char)socks5_host_len;
+ memcpy(&pbuf[i = 5], socks5_host, socks5_host_len);
+ i += socks5_host_len;
+ /* C99 */{
+ unsigned short x; /* XXX 16-bit? */
+
+ x = htons(socks5_port);
+ memcpy(&pbuf[i], (unsigned char*)&x, sizeof x);
+ i += sizeof x;
+ }
+ if((size_t)write(*s, pbuf, i) != i)
+ goto jerrsocks;
+
+ /* Connect result */
+ if((i = HTDoRead(*s, pbuf, 4)) != 4)
+ goto jerrsocks;
+ /* Version 5, reserved must be 0 */
+ if(pbuf[0] != 0x05 || pbuf[2] != 0x00)
+ goto jesocksreply;
+ /* Result */
+ switch(pbuf[1]){
+ case 0x00: emsg = NULL; break;
+ case 0x01: emsg = N_("SOCKS server failure"); break;
+ case 0x02: emsg = N_("connection not allowed by ruleset"); break;
+ case 0x03: emsg = N_("network unreachable"); break;
+ case 0x04: emsg = N_("host unreachable"); break;
+ case 0x05: emsg = N_("connection refused"); break;
+ case 0x06: emsg = N_("TTL expired"); break;
+ case 0x07: emsg = N_("command not supported"); break;
+ case 0x08: emsg = N_("address type not supported"); break;
+ default: emsg = N_("unknown SOCKS error code"); break;
+ }
+ if(emsg != NULL)
+ goto jesocksreplymsg;
+
+ /* Address type variable; read the BND.PORT with it.
+ * This is actually false since RFC 1928 says that the BND.ADDR reply
+ * to CONNECT contains the IP address, so only 0x01 and 0x04 are
+ * allowed */
+ switch(pbuf[3]){
+ case 0x01: i = 4; break;
+ case 0x03: i = 1; break;
+ case 0x04: i = 16; break;
+ default: goto jesocksreply;
+ }
+ i += sizeof(unsigned short);
+ if((size_t)HTDoRead(*s, pbuf, i) != i)
+ goto jerrsocks;
+ if(i == 1 + sizeof(unsigned short)){
+ i = pbuf[0];
+ if((size_t)HTDoRead(*s, pbuf, i) != i)
+ goto jerrsocks;
+ }
+ }
+
+jout:
+ if(socks5_proxy != NULL){
+ FREE(url);
+ FREE(protocol);
+ FREE(socks5_host);
+ }
+ if(host != NULL);
+ FREE(host);
+ if(line != NULL)
+ FREE(line);
return status;
}
diff --git a/lynx.man b/lynx.man
index ff4eb1b8..5a43c71a 100644
--- a/lynx.man
+++ b/lynx.man
@@ -804,6 +804,11 @@ If enabled the transfer rate is shown in bytes/second.
If disabled, no transfer rate is shown.
Use lynx.cfg or the options menu to select KB/second and/or ETA.
.TP
+.B \-socks5-proxy=URL
+(Via which) SOCKS5 proxy to connect.
+This controls the builtin SOCKS5 support, and is therefore unrelated to
+the option \fB\-nosocks\fP.
+.TP
.B \-soft_dquotes
toggles emulation of the old Netscape and Mosaic bug which
treated \*(``>\*('' as a co-terminator for double-quotes and tags.
diff --git a/src/LYGlobalDefs.h b/src/LYGlobalDefs.h
index e1203c02..577a5948 100644
--- a/src/LYGlobalDefs.h
+++ b/src/LYGlobalDefs.h
@@ -441,6 +441,7 @@ extern "C" {
extern BOOLEAN debug_display_partial; /* show with MessageSecs delay */
extern BOOLEAN display_partial_flag; /* permanent flag, not mutable */
#endif
+ extern char *socks5_proxy;
extern char *form_post_data; /* User data for post form */
extern char *form_get_data; /* User data for get form */
extern char *http_error_file; /* Place HTTP status code in this file */
diff --git a/src/LYMain.c b/src/LYMain.c
index 36c22ed5..46b8cee8 100644
--- a/src/LYMain.c
+++ b/src/LYMain.c
@@ -635,6 +635,8 @@ BOOLEAN debug_display_partial = FALSE; /* Show with MessageSecs delay */
int partial_threshold = -1; /* # of lines to be d/l'ed until we repaint */
#endif
+char *socks5_proxy = NULL;
+
BOOLEAN LYNonRestartingSIGWINCH = FALSE;
BOOLEAN LYReuseTempfiles = FALSE;
BOOLEAN LYUseBuiltinSuffixes = TRUE;
@@ -3910,6 +3912,10 @@ saves session to that file on exit"
"toggles display of transfer rate"
),
#endif
+ PARSE_STR(
+ "socks5-proxy", 2|NEED_LYSTRING_ARG, socks5_proxy,
+ "=URL\n(via which) SOCKS5 proxy to connect (unrelated to -nosocks!)"
+ ),
PARSE_SET(
"soft_dquotes", 4|TOGGLE_ARG, soft_dquotes,
"toggles emulation of the old Netscape and Mosaic\n\
_______________________________________________
Lynx-dev mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/lynx-dev