mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
Added option http-version
This commit is contained in:
parent
9f632ec651
commit
454a499401
9 changed files with 116 additions and 22 deletions
5
CHANGES
5
CHANGES
|
@ -20,6 +20,11 @@ Features:
|
||||||
Added option ipv6-join-source-group.
|
Added option ipv6-join-source-group.
|
||||||
Thanks to Martin Buck and David Schweizer for sending patches.
|
Thanks to Martin Buck and David Schweizer for sending patches.
|
||||||
|
|
||||||
|
Added option http-version to PROXY-CONNECT address to support servers
|
||||||
|
that are not able to handle HTTP version 1.0
|
||||||
|
Test: PROXY_HTTPVERSION
|
||||||
|
Feature inspired by Robin Palotai.
|
||||||
|
|
||||||
Corrections:
|
Corrections:
|
||||||
When a sub process (EXEC, SYSTEM) terminated with exit code other than
|
When a sub process (EXEC, SYSTEM) terminated with exit code other than
|
||||||
0, its last sent data might have been lost depending on timing of read/
|
0, its last sent data might have been lost depending on timing of read/
|
||||||
|
|
|
@ -2421,6 +2421,10 @@ Options that can be provided with HTTP type addresses. The only HTTP address
|
||||||
currently implemented is link(proxy-connect)(ADDRESS_PROXY_CONNECT).
|
currently implemented is link(proxy-connect)(ADDRESS_PROXY_CONNECT).
|
||||||
|
|
||||||
startdit()
|
startdit()
|
||||||
|
label(OPTION_HTTP_VERSION)dit(bf(tt(http-version=<string>)))
|
||||||
|
Changes the default "1.0" that is sent to the server in the initial HTTP
|
||||||
|
request. Currently it has not other effect, in particular it does not
|
||||||
|
provide any means to send a Host header.
|
||||||
label(OPTION_PROXYPORT)dit(bf(tt(proxyport=<TCP service>)))
|
label(OPTION_PROXYPORT)dit(bf(tt(proxyport=<TCP service>)))
|
||||||
Overrides the default HTTP proxy port 8080 with
|
Overrides the default HTTP proxy port 8080 with
|
||||||
link(<TCP service>)(TYPE_TCP_SERVICE).
|
link(<TCP service>)(TYPE_TCP_SERVICE).
|
||||||
|
|
4
proxy.sh
4
proxy.sh
|
@ -7,8 +7,8 @@
|
||||||
# accepts and answers correct HTTP CONNECT requests on stdio, and tries to
|
# accepts and answers correct HTTP CONNECT requests on stdio, and tries to
|
||||||
# establish the connection to the given server.
|
# establish the connection to the given server.
|
||||||
# it is required for socats test.sh
|
# it is required for socats test.sh
|
||||||
# for TCP, use this script as:
|
# for TCP, use this script like:
|
||||||
# socat tcp-l:8080,reuseaddr,fork exec:"proxy.sh",nofork
|
# socat TCP-L:8080,reuseaddr,fork EXEC:"proxy.sh",nofork
|
||||||
|
|
||||||
# 20130622 GR allow hostnames, not only IP addresses
|
# 20130622 GR allow hostnames, not only IP addresses
|
||||||
|
|
||||||
|
|
19
proxyecho.sh
19
proxyecho.sh
|
@ -7,7 +7,9 @@
|
||||||
# accepts and answers correct HTTP CONNECT requests, but then just echoes data.
|
# accepts and answers correct HTTP CONNECT requests, but then just echoes data.
|
||||||
# it is required for test.sh
|
# it is required for test.sh
|
||||||
# for TCP, use this script as:
|
# for TCP, use this script as:
|
||||||
# socat tcp-l:8080,reuseaddr,crlf system:"proxyecho.sh"
|
# socat TCP-L:8080,reuseaddr,crlf SYSTEM:"proxyecho.sh"
|
||||||
|
|
||||||
|
# 20230423 GR Added option -V to require particular HTTP version
|
||||||
|
|
||||||
if type socat >/dev/null 2>&1; then
|
if type socat >/dev/null 2>&1; then
|
||||||
SOCAT=socat
|
SOCAT=socat
|
||||||
|
@ -24,11 +26,12 @@ HP-UX|OSF1)
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
SPACES=" "
|
SPACES=" " REQVER=1.0
|
||||||
while [ -n "$1" ]; do
|
while [ -n "$1" ]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-w) n="$2"; while [ "$n" -gt 0 ]; do SPACES="$SPACES "; n=$((n-1)); done
|
-w) n="$2"; while [ "$n" -gt 0 ]; do SPACES="$SPACES "; n=$((n-1)); done
|
||||||
shift ;;
|
shift ;;
|
||||||
|
-V) shift; REQVER="$1" ;;
|
||||||
#-s) STAT="$2"; shift ;;
|
#-s) STAT="$2"; shift ;;
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
|
@ -36,14 +39,18 @@ done
|
||||||
|
|
||||||
# read and parse HTTP request
|
# read and parse HTTP request
|
||||||
read l
|
read l
|
||||||
if echo "$l" |egrep '^CONNECT +[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+ +HTTP/1.[01]$' >/dev/null
|
if ! echo "$l" |egrep '^CONNECT +[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+ +HTTP/[1-3].[0-9]$' >/dev/null
|
||||||
then
|
then
|
||||||
: go on below
|
|
||||||
else
|
|
||||||
echo "HTTP/1.0${SPACES}500 Bad Request"
|
echo "HTTP/1.0${SPACES}500 Bad Request"
|
||||||
echo
|
echo
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
if ! echo "$l" |egrep '^CONNECT +[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+ +HTTP/'"$REQVER"'$' >/dev/null
|
||||||
|
then
|
||||||
|
echo "HTTP/1.0${SPACES}426 Upgrade Required"
|
||||||
|
echo
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
# read more headers until empty line
|
# read more headers until empty line
|
||||||
while [ -n "$l" ]; do
|
while [ -n "$l" ]; do
|
||||||
|
@ -51,7 +58,7 @@ while [ -n "$l" ]; do
|
||||||
done
|
done
|
||||||
|
|
||||||
# send status
|
# send status
|
||||||
echo "HTTP/1.0${SPACES}200 OK"
|
echo "HTTP/$REQVER${SPACES}200 OK"
|
||||||
# send empty line
|
# send empty line
|
||||||
echo
|
echo
|
||||||
|
|
||||||
|
|
93
test.sh
93
test.sh
|
@ -4128,27 +4128,31 @@ te="$td/test$N.stderr"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
|
da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
|
||||||
newport tcp4 # provide free port number in $PORT
|
newport tcp4 # provide free port number in $PORT
|
||||||
#CMD2="$TRACE $SOCAT $opts tcp-l:$PORT,crlf SYSTEM:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\""
|
#CMD2="$TRACE $SOCAT $opts TCP-L:$PORT,crlf SYSTEM:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\""
|
||||||
CMD2="$TRACE $SOCAT $opts tcp4-l:$PORT,reuseaddr,crlf exec:\"/usr/bin/env bash proxyecho.sh -w 2\""
|
CMD0="$TRACE $SOCAT $opts TCP4-L:$PORT,reuseaddr,crlf EXEC:\"/usr/bin/env bash proxyecho.sh -w 2\""
|
||||||
CMD="$TRACE $SOCAT $opts - proxy:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT"
|
CMD1="$TRACE $SOCAT $opts - PROXY:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
eval "$CMD2 2>\"${te}1\" &"
|
eval "$CMD0 2>\"${te}1\" &"
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
waittcp4port $PORT 1
|
waittcp4port $PORT 1
|
||||||
echo "$da" |$CMD >"$tf" 2>"${te}2"
|
echo "$da" |$CMD1 >"$tf" 2>"${te}0"
|
||||||
if ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
if ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||||
echo "$CMD2 &"
|
echo "$CMD0 &"
|
||||||
echo "$CMD"
|
cat "${te}0" >&2
|
||||||
cat "${te}1"
|
echo "$CMD1"
|
||||||
cat "${te}2"
|
cat "${te}1" >&2
|
||||||
|
echo "diff:"
|
||||||
cat "$tdiff"
|
cat "$tdiff"
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
else
|
else
|
||||||
$PRINTF "$OK\n"
|
$PRINTF "$OK\n"
|
||||||
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
numOK=$((numOK+1))
|
if [ "$debug" ]; then cat "${te}0" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
|
||||||
|
if [ "$debug" ]; then cat "${te}1" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
fi
|
fi
|
||||||
kill $pid 2>/dev/null
|
kill $pid 2>/dev/null
|
||||||
wait
|
wait
|
||||||
|
@ -15153,6 +15157,71 @@ fi # NUMCOND
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# Test the http-version of the PROXY-CONNECT address
|
||||||
|
NAME=PROXY_HTTPVERSION
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%proxy%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: PROXY-CONNECT with option http-version"
|
||||||
|
if ! eval $NUMCOND; then :;
|
||||||
|
elif ! $(type proxyecho.sh >/dev/null 2>&1); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}proxyecho.sh not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! F=$(testfeats IP4 TCP LISTEN EXEC STDIO PROXY); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! A=$(testaddrs TCP4-LISTEN EXEC STDIO PROXY-CONNECT); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! o=$(testoptions so-reuseaddr crlf pf proxyport http-version) >/dev/null; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! runsip4 >/dev/null; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
else
|
||||||
|
ts="$td/test$N.sh"
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
|
||||||
|
CMD0="$TRACE $SOCAT $opts TCP4-L:$PORT,reuseaddr,crlf EXEC:\"/usr/bin/env bash proxyecho.sh -V 1.1\""
|
||||||
|
CMD1="$TRACE $SOCAT $opts - PROXY:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT,http-version=1.1"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
eval "$CMD0 2>\"${te}1\" &"
|
||||||
|
pid=$! # background process id
|
||||||
|
waittcp4port $PORT 1
|
||||||
|
echo "$da" |$CMD1 >"$tf" 2>"${te}0"
|
||||||
|
if ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||||
|
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||||
|
echo "$CMD0 &" >&2
|
||||||
|
cat "${te}0"
|
||||||
|
echo "$CMD1" >&2
|
||||||
|
cat "${te}1"
|
||||||
|
echo "diff:"
|
||||||
|
cat "$tdiff"
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
else
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
|
if [ "$debug" ]; then cat "${te}0" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
|
||||||
|
if [ "$debug" ]; then cat "${te}1" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
fi
|
||||||
|
kill $pid 2>/dev/null
|
||||||
|
wait
|
||||||
|
fi ;; # NUMCOND, feats
|
||||||
|
esac
|
||||||
|
PORT=$((PORT+1))
|
||||||
|
|
||||||
|
|
||||||
# end of common tests
|
# end of common tests
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
|
|
@ -27,6 +27,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
|
|
||||||
const struct optdesc opt_proxyport = { "proxyport", NULL, OPT_PROXYPORT, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
const struct optdesc opt_proxyport = { "proxyport", NULL, OPT_PROXYPORT, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
||||||
const struct optdesc opt_ignorecr = { "ignorecr", NULL, OPT_IGNORECR, GROUP_HTTP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
|
const struct optdesc opt_ignorecr = { "ignorecr", NULL, OPT_IGNORECR, GROUP_HTTP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
|
||||||
|
const struct optdesc opt_http_version = { "http-version", NULL, OPT_HTTP_VERSION, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
||||||
const struct optdesc opt_proxy_resolve = { "proxy-resolve", "resolve", OPT_PROXY_RESOLVE, GROUP_HTTP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
|
const struct optdesc opt_proxy_resolve = { "proxy-resolve", "resolve", OPT_PROXY_RESOLVE, GROUP_HTTP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
|
||||||
const struct optdesc opt_proxy_authorization = { "proxy-authorization", "proxyauth", OPT_PROXY_AUTHORIZATION, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
const struct optdesc opt_proxy_authorization = { "proxy-authorization", "proxyauth", OPT_PROXY_AUTHORIZATION, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
||||||
const struct optdesc opt_proxy_authorization_file = { "proxy-authorization-file", "proxyauthfile", OPT_PROXY_AUTHORIZATION_FILE, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
const struct optdesc opt_proxy_authorization_file = { "proxy-authorization-file", "proxyauthfile", OPT_PROXY_AUTHORIZATION_FILE, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
||||||
|
@ -239,6 +240,7 @@ int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts,
|
||||||
|
|
||||||
retropt_bool(opts, OPT_IGNORECR, &proxyvars->ignorecr);
|
retropt_bool(opts, OPT_IGNORECR, &proxyvars->ignorecr);
|
||||||
retropt_bool(opts, OPT_PROXY_RESOLVE, &proxyvars->doresolve);
|
retropt_bool(opts, OPT_PROXY_RESOLVE, &proxyvars->doresolve);
|
||||||
|
retropt_string(opts, OPT_HTTP_VERSION, &proxyvars->version);
|
||||||
retropt_string(opts, OPT_PROXY_AUTHORIZATION, &proxyvars->authstring);
|
retropt_string(opts, OPT_PROXY_AUTHORIZATION, &proxyvars->authstring);
|
||||||
retropt_string(opts, OPT_PROXY_AUTHORIZATION_FILE, &proxyvars->authfile);
|
retropt_string(opts, OPT_PROXY_AUTHORIZATION_FILE, &proxyvars->authfile);
|
||||||
|
|
||||||
|
@ -331,8 +333,11 @@ int _xioopen_proxy_connect(struct single *xfd,
|
||||||
ssize_t sresult;
|
ssize_t sresult;
|
||||||
|
|
||||||
/* generate proxy request header - points to final target */
|
/* generate proxy request header - points to final target */
|
||||||
rv = snprintf(request, CONNLEN, "CONNECT %s:%u HTTP/1.0\r\n",
|
if (proxyvars->version == NULL) {
|
||||||
proxyvars->targetaddr, proxyvars->targetport);
|
proxyvars->version = "1.0";
|
||||||
|
}
|
||||||
|
rv = snprintf(request, CONNLEN, "CONNECT %s:%u HTTP/%s\r\n",
|
||||||
|
proxyvars->targetaddr, proxyvars->targetport, proxyvars->version);
|
||||||
if (rv >= CONNLEN || rv < 0) {
|
if (rv >= CONNLEN || rv < 0) {
|
||||||
Error("_xioopen_proxy_connect(): PROXY CONNECT buffer too small");
|
Error("_xioopen_proxy_connect(): PROXY CONNECT buffer too small");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
struct proxyvars {
|
struct proxyvars {
|
||||||
bool ignorecr;
|
bool ignorecr;
|
||||||
|
char *version;
|
||||||
bool doresolve;
|
bool doresolve;
|
||||||
char *authstring;
|
char *authstring;
|
||||||
char *authfile;
|
char *authfile;
|
||||||
|
@ -17,6 +18,7 @@ struct proxyvars {
|
||||||
|
|
||||||
extern const struct optdesc opt_proxyport;
|
extern const struct optdesc opt_proxyport;
|
||||||
extern const struct optdesc opt_ignorecr;
|
extern const struct optdesc opt_ignorecr;
|
||||||
|
extern const struct optdesc opt_http_version;
|
||||||
extern const struct optdesc opt_proxy_resolve;
|
extern const struct optdesc opt_proxy_resolve;
|
||||||
extern const struct optdesc opt_proxy_authorization;
|
extern const struct optdesc opt_proxy_authorization;
|
||||||
extern const struct optdesc opt_proxy_authorization_file;
|
extern const struct optdesc opt_proxy_authorization_file;
|
||||||
|
|
|
@ -613,6 +613,7 @@ const struct optname optionnames[] = {
|
||||||
#if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
|
#if WITH_LIBWRAP && defined(HAVE_HOSTS_DENY_TABLE)
|
||||||
IF_IPAPP ("hosts-deny", &opt_tcpwrap_hosts_deny_table)
|
IF_IPAPP ("hosts-deny", &opt_tcpwrap_hosts_deny_table)
|
||||||
#endif
|
#endif
|
||||||
|
IF_PROXY ("http-version", &opt_http_version)
|
||||||
IF_TERMIOS("hup", &opt_hupcl)
|
IF_TERMIOS("hup", &opt_hupcl)
|
||||||
IF_TERMIOS("hupcl", &opt_hupcl)
|
IF_TERMIOS("hupcl", &opt_hupcl)
|
||||||
#ifdef I_POP
|
#ifdef I_POP
|
||||||
|
|
|
@ -337,6 +337,7 @@ enum e_optcode {
|
||||||
OPT_GROUP_EARLY,
|
OPT_GROUP_EARLY,
|
||||||
OPT_GROUP_LATE,
|
OPT_GROUP_LATE,
|
||||||
OPT_HISTORY_FILE, /* readline history file */
|
OPT_HISTORY_FILE, /* readline history file */
|
||||||
|
OPT_HTTP_VERSION,
|
||||||
OPT_HUPCL, /* termios.c_cflag */
|
OPT_HUPCL, /* termios.c_cflag */
|
||||||
OPT_ICANON, /* termios.c_lflag */
|
OPT_ICANON, /* termios.c_lflag */
|
||||||
OPT_ICRNL, /* termios.c_iflag */
|
OPT_ICRNL, /* termios.c_iflag */
|
||||||
|
|
Loading…
Reference in a new issue