Commit 61db4824 authored by David Kalnischkies's avatar David Kalnischkies

implement socks5h proxy support for http method

Socks support is a requested feature in sofar that the internet is
actually believing Acquire::socks::Proxy would exist. It doesn't and
this commit isn't adding it as that isn't how our configuration works,
but it allows Acquire::http::Proxy="socks5h://…". The HTTPS method was
changed already to support socks proxies (all versions) via curl. This
commit implements only SOCKS5 (RFC1928) with no auth or pass&user auth
(RFC1929), but not GSSAPI which is required by the RFC. The 'h' in the
protocol name further indicates that DNS resolution is delegated to the
socks proxy rather than performed locally.

The implementation works and was tested with Tor as socks proxy for
which implementing socks5h only can actually be considered a feature.

Closes: 744934
parent 30060442
......@@ -2443,6 +2443,37 @@ bool FileFd::Read(void *To,unsigned long long Size,unsigned long long *Actual)
}
return FileFdError(_("read, still have %llu to read but none left"), Size);
}
bool FileFd::Read(int const Fd, void *To, unsigned long long Size, unsigned long long * const Actual)
{
ssize_t Res = 1;
errno = 0;
if (Actual != nullptr)
*Actual = 0;
*static_cast<char *>(To) = '\0';
while (Res > 0 && Size > 0)
{
Res = read(Fd, To, Size);
if (Res < 0)
{
if (errno == EINTR)
{
Res = 1;
errno = 0;
continue;
}
return _error->Errno("read", _("Read error"));
}
To = static_cast<char *>(To) + Res;
Size -= Res;
if (Actual != 0)
*Actual += Res;
}
if (Size == 0)
return true;
if (Actual != nullptr)
return true;
return _error->Error(_("read, still have %llu to read but none left"), Size);
}
/*}}}*/
// FileFd::ReadLine - Read a complete line from the file /*{{{*/
......
......@@ -86,6 +86,7 @@ class FileFd
return Read(To,Size);
}
bool Read(void *To,unsigned long long Size,unsigned long long *Actual = 0);
bool static Read(int const Fd, void *To, unsigned long long Size, unsigned long long * const Actual = 0);
char* ReadLine(char *To, unsigned long long const Size);
bool Flush();
bool Write(const void *From,unsigned long long Size);
......
This diff is collapsed.
......@@ -67,7 +67,7 @@ class CircleBuf
// Read data in
bool Read(int Fd);
bool Read(std::string Data);
bool Read(std::string const &Data);
// Write data out
bool Write(int Fd);
......
#!/bin/sh
set -e
TESTDIR="$(readlink -f "$(dirname "$0")")"
. "$TESTDIR/framework"
setupenvironment
# We don't do a real proxy here, we just look how the implementation
# reacts to certain responses from a "proxy" provided by socat
# Checks HTTP, but requesting https instead will check HTTPS (curl) which
# uses different error messages through – also: https://github.com/curl/curl/issues/944
# FIXME: Not run automatically as it uses a hardcoded port (5555)
msgtest 'Check that everything is installed' 'socat'
if dpkg-checkbuilddeps -d 'socat' /dev/null >/dev/null 2>&1; then
msgpass
else
msgskip "$(command dpkg -l socat)"
exit
fi
runclient() {
# this doesn't need to be an actually reachable webserver for this test
# in fact, its better if it isn't.
rm -f index.html
apthelper download-file http://localhost:2903/ index.html \
-o Acquire::http::Proxy="socks5h://${1}localhost:5555" \
-o Acquire::http::Timeout=2 -o Debug::Acquire::http=1 > client.output 2>&1 || true
}
runserver() {
socat -x tcp-listen:5555,reuseaddr \
system:"echo -n '$*' | xxd -r -p; echo 'HTTP/1.1 200 OK'; echo 'Content-Length: 5'; echo 'Connection: close'; echo; echo 'HTML'" \
> server.output 2>&1 &
}
PROXY="socks5h://localhost:5555"
msgmsg 'SOCKS does not run'
runclient
testsuccess grep 'Could not connect to localhost:5555' client.output
msgmsg 'SOCKS greets back with wrong version'
runserver '04 00'
runclient
testsuccess grep 'greets back with wrong version: 4' client.output
msgmsg 'SOCKS tries GSSAPI auth we have not advertised'
runserver '05 01'
runclient
testsuccess grep 'greets back having not found a common authorization method: 1' client.output
msgmsg 'SOCKS tries user&pass auth we have not advertised'
runserver '05 02'
runclient
testsuccess grep 'pass auth, but we had not offered it' client.output
msgmsg 'SOCKS user:pass wrong version'
runserver '05 02' '05 00'
runclient 'user:pass@'
testsuccess grep 'auth status response with wrong version: 5' client.output
msgmsg 'SOCKS user:pass wrong auth'
runserver '05 02' '01 01'
runclient 'user:pass@'
testsuccess grep 'reported authorization failure: username or password incorrect? (1)' client.output
msgmsg 'SOCKS user:pass request not granted no hostname'
runserver '05 02' '01 00' '05 01 00 03 00 1f 90'
runclient 'user:pass@'
testsuccess grep 'grant the connect to :8080 due to: general SOCKS server failure (1)' client.output
msgmsg 'SOCKS user:pass request not granted with hostname'
runserver '05 02' '01 00' '05 01 00 03 09 68 6f 73 74 6c 6f 63 61 6c 1f 90'
runclient 'user:pass@'
testsuccess grep 'grant the connect to hostlocal:8080 due to: general SOCKS server failure (1)' client.output
msgmsg 'SOCKS user:pass request not granted ipv4'
runserver '05 02' '01 00' '05 04 00 01 ac 10 fe 01 1f 90'
runclient 'user:pass@'
testsuccess grep 'grant the connect to 172.16.254.1:8080 due to: Host unreachable (4)' client.output
msgmsg 'SOCKS user:pass request not granted ipv6'
runserver '05 02' '01 00' '05 12 00 04 20 01 0d b8 ac 10 fe 00 00 00 00 00 00 00 00 00 1f 90'
runclient 'user:pass@'
testsuccess grep 'grant the connect to \[2001:0DB8:AC10:FE00:0000:0000:0000:0000\]:8080 due to: Unknown error (18)' client.output
msgmsg 'SOCKS user:pass request granted ipv4'
runserver '05 02' '01 00' '05 00 00 01 ac 10 fe 01 1f 90'
runclient 'user:pass@'
testequal "http: SOCKS proxy $PROXY connection established to 172.16.254.1:8080" head -n 1 client.output
testfileequal index.html 'HTML'
msgmsg 'SOCKS user:pass request granted ipv6'
runserver '05 02' '01 00' '05 00 00 04 20 01 0d b8 ac 10 fe 00 00 00 00 00 00 00 00 00 1f 90'
runclient 'user:pass@'
testequal "http: SOCKS proxy $PROXY connection established to [2001:0DB8:AC10:FE00:0000:0000:0000:0000]:8080" head -n 1 client.output
testfileequal index.html 'HTML'
msgmsg 'SOCKS no auth no hostname'
runserver '05 00 05 00 00 03 00 1f 90'
runclient
testequal "http: SOCKS proxy $PROXY connection established to :8080" head -n 1 client.output
testfileequal index.html 'HTML'
msgmsg 'SOCKS no auth with hostname'
runserver '05 00 05 00 00 03 09 68 6f 73 74 6c 6f 63 61 6c 1f 90'
runclient
testequal "http: SOCKS proxy $PROXY connection established to hostlocal:8080" head -n 1 client.output
testfileequal index.html 'HTML'
msgmsg 'SOCKS user-only request granted ipv4'
runserver '05 02' '01 00' '05 00 00 01 ac 10 fe 01 1f 90'
runclient 'apt@'
testequal "http: SOCKS proxy $PROXY connection established to 172.16.254.1:8080" head -n 1 client.output
testfileequal index.html 'HTML'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment