mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 07:22:34 +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.
|
||||
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:
|
||||
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/
|
||||
|
|
|
@ -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).
|
||||
|
||||
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>)))
|
||||
Overrides the default HTTP proxy port 8080 with
|
||||
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
|
||||
# establish the connection to the given server.
|
||||
# it is required for socats test.sh
|
||||
# for TCP, use this script as:
|
||||
# socat tcp-l:8080,reuseaddr,fork exec:"proxy.sh",nofork
|
||||
# for TCP, use this script like:
|
||||
# socat TCP-L:8080,reuseaddr,fork EXEC:"proxy.sh",nofork
|
||||
|
||||
# 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.
|
||||
# it is required for test.sh
|
||||
# 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
|
||||
SOCAT=socat
|
||||
|
@ -24,11 +26,12 @@ HP-UX|OSF1)
|
|||
;;
|
||||
esac
|
||||
|
||||
SPACES=" "
|
||||
SPACES=" " REQVER=1.0
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
-w) n="$2"; while [ "$n" -gt 0 ]; do SPACES="$SPACES "; n=$((n-1)); done
|
||||
shift ;;
|
||||
-V) shift; REQVER="$1" ;;
|
||||
#-s) STAT="$2"; shift ;;
|
||||
esac
|
||||
shift
|
||||
|
@ -36,14 +39,18 @@ done
|
|||
|
||||
# read and parse HTTP request
|
||||
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
|
||||
: go on below
|
||||
else
|
||||
echo "HTTP/1.0${SPACES}500 Bad Request"
|
||||
echo
|
||||
exit
|
||||
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
|
||||
while [ -n "$l" ]; do
|
||||
|
@ -51,7 +58,7 @@ while [ -n "$l" ]; do
|
|||
done
|
||||
|
||||
# send status
|
||||
echo "HTTP/1.0${SPACES}200 OK"
|
||||
echo "HTTP/$REQVER${SPACES}200 OK"
|
||||
# send empty line
|
||||
echo
|
||||
|
||||
|
|
93
test.sh
93
test.sh
|
@ -4128,27 +4128,31 @@ te="$td/test$N.stderr"
|
|||
tdiff="$td/test$N.diff"
|
||||
da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
|
||||
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 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"
|
||||
#CMD2="$TRACE $SOCAT $opts TCP-L:$PORT,crlf SYSTEM:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\""
|
||||
CMD0="$TRACE $SOCAT $opts TCP4-L:$PORT,reuseaddr,crlf EXEC:\"/usr/bin/env bash proxyecho.sh -w 2\""
|
||||
CMD1="$TRACE $SOCAT $opts - PROXY:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT"
|
||||
printf "test $F_n $TEST... " $N
|
||||
eval "$CMD2 2>\"${te}1\" &"
|
||||
eval "$CMD0 2>\"${te}1\" &"
|
||||
pid=$! # background process id
|
||||
waittcp4port $PORT 1
|
||||
echo "$da" |$CMD >"$tf" 2>"${te}2"
|
||||
echo "$da" |$CMD1 >"$tf" 2>"${te}0"
|
||||
if ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||
echo "$CMD2 &"
|
||||
echo "$CMD"
|
||||
cat "${te}1"
|
||||
cat "${te}2"
|
||||
echo "$CMD0 &"
|
||||
cat "${te}0" >&2
|
||||
echo "$CMD1"
|
||||
cat "${te}1" >&2
|
||||
echo "diff:"
|
||||
cat "$tdiff"
|
||||
numFAIL=$((numFAIL+1))
|
||||
listFAIL="$listFAIL $N"
|
||||
else
|
||||
$PRINTF "$OK\n"
|
||||
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
|
||||
numOK=$((numOK+1))
|
||||
$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
|
||||
|
@ -15153,6 +15157,71 @@ fi # NUMCOND
|
|||
esac
|
||||
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
|
||||
|
||||
##################################################################################
|
||||
|
|
|
@ -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_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_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 };
|
||||
|
@ -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_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_FILE, &proxyvars->authfile);
|
||||
|
||||
|
@ -331,8 +333,11 @@ int _xioopen_proxy_connect(struct single *xfd,
|
|||
ssize_t sresult;
|
||||
|
||||
/* generate proxy request header - points to final target */
|
||||
rv = snprintf(request, CONNLEN, "CONNECT %s:%u HTTP/1.0\r\n",
|
||||
proxyvars->targetaddr, proxyvars->targetport);
|
||||
if (proxyvars->version == NULL) {
|
||||
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) {
|
||||
Error("_xioopen_proxy_connect(): PROXY CONNECT buffer too small");
|
||||
return -1;
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
struct proxyvars {
|
||||
bool ignorecr;
|
||||
char *version;
|
||||
bool doresolve;
|
||||
char *authstring;
|
||||
char *authfile;
|
||||
|
@ -17,6 +18,7 @@ struct proxyvars {
|
|||
|
||||
extern const struct optdesc opt_proxyport;
|
||||
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_authorization;
|
||||
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_IPAPP ("hosts-deny", &opt_tcpwrap_hosts_deny_table)
|
||||
#endif
|
||||
IF_PROXY ("http-version", &opt_http_version)
|
||||
IF_TERMIOS("hup", &opt_hupcl)
|
||||
IF_TERMIOS("hupcl", &opt_hupcl)
|
||||
#ifdef I_POP
|
||||
|
|
|
@ -337,6 +337,7 @@ enum e_optcode {
|
|||
OPT_GROUP_EARLY,
|
||||
OPT_GROUP_LATE,
|
||||
OPT_HISTORY_FILE, /* readline history file */
|
||||
OPT_HTTP_VERSION,
|
||||
OPT_HUPCL, /* termios.c_cflag */
|
||||
OPT_ICANON, /* termios.c_lflag */
|
||||
OPT_ICRNL, /* termios.c_iflag */
|
||||
|
|
Loading…
Reference in a new issue