Option proxy-authorization-file

This commit is contained in:
Gerhard Rieger 2020-12-26 16:04:50 +01:00
parent 50bdb453dd
commit 1c7ddfef73
7 changed files with 129 additions and 2 deletions

View file

@ -164,6 +164,12 @@ New features:
Test: UDP_DATAGRAM_SOURCEPORT Test: UDP_DATAGRAM_SOURCEPORT
Feature inspired by Hans Bueckler for SSDP inquiry (for UPnP) Feature inspired by Hans Bueckler for SSDP inquiry (for UPnP)
New option proxy-authorization-file reads PROXY-CONNECT credentials
from file and makes it possible to hide this data from the process
table.
Test: PROXYAUTHFILE
Thanks to Charles Stephens for sending an initial patch.
####################### V 1.7.3.4: ####################### V 1.7.3.4:
Corrections: Corrections:

View file

@ -2343,13 +2343,17 @@ label(OPTION_IGNORECR)dit(bf(tt(ignorecr)))
server violates this standard, socat might not understand its answer. server violates this standard, socat might not understand its answer.
This option directs socat to interprete NL as line terminator and This option directs socat to interprete NL as line terminator and
to ignore CR in the answer. Nevertheless, socat sends CR+NL to the proxy. to ignore CR in the answer. Nevertheless, socat sends CR+NL to the proxy.
label(OPTION_PROXY_AUTHORIZATION)dit(bf(tt(proxyauth=<username>:<password>))) label(OPTION_PROXY_AUTHORIZATION)dit(bf(tt(proxy-authorization=<username>:<password>)))
Provide "basic" authentication to the proxy server. The argument to the Provide "basic" authentication to the proxy server. The argument to the
option is used with a "Proxy-Authorization: Base" header in base64 encoded option is used with a "Proxy-Authorization: Basic" header in base64 encoded
form.nl() form.nl()
Note: username and password are visible for every user on the local machine Note: username and password are visible for every user on the local machine
in the process list; username and password are transferred to the proxy in the process list; username and password are transferred to the proxy
server unencrypted (base64 encoded) and might be sniffed. server unencrypted (base64 encoded) and might be sniffed.
label(OPTION_PROXY_AUTHORIZATION_FILE)dit(bf(tt(proxy-authorization-file=<filename>)))
Like option link(proxy-authorization)(OPTION_PROXY_AUTHORIZATION), but the
credentials are read from the file and therefore not visible in the process
list.nl()
label(OPTION_PROXY_RESOLVE)dit(bf(tt(resolve))) label(OPTION_PROXY_RESOLVE)dit(bf(tt(resolve)))
Per default, socat sends to the proxy a CONNECT request containing the Per default, socat sends to the proxy a CONNECT request containing the
target hostname. With this option, socat resolves the hostname locally and target hostname. With this option, socat resolves the hostname locally and

67
test.sh
View file

@ -14521,6 +14521,73 @@ PORT=$((PORT+1))
N=$((N+1)) N=$((N+1))
# Test the proxy-authorization-file option
NAME=PROXYAUTHFILE
case "$TESTS" in
*%$N%*|*%functions%*|*%proxyconnect%*|*%proxy%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)
TEST="$NAME: proxy-authorization-file option"
if ! eval $NUMCOND; then :;
elif ! testfeats proxy >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}PROXY not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! testoptions proxy-authorization-file >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}Option proxy-authorization-file not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
else
ta="$td/test$N.auth"
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="{ echo -e \"HTTP/1.0 200 OK\\n\"; sleep 2; } |$TRACE $SOCAT $opts - TCP4-L:$PORT,$REUSEADDR,crlf"
CMD1="$TRACE $SOCAT $opts FILE:/dev/null PROXY-CONNECT:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT,proxy-authorization-file=$ta"
printf "test $F_n $TEST... " $N
echo "user:s3cr3t" >$ta
eval "$CMD0 >${tf}0 2>${te}0 &"
pid0=$! # background process id
waittcp4port $PORT 1
$CMD1 >"${tf}1" 2>"${te}1"
rc1=$?
kill $pid0 2>/dev/null
wait $pid0
if [ $rc1 -ne 0 ]; then
$PRINTF "$FAILED\n"
echo "$CMD0 &" >&2
cat "${te}0" >&2
echo "$CMD1" >&2
cat "${te}1" >&2
cat "${tf}0" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
elif ! grep -q '^Proxy-authorization: Basic dXNlcjpzM2NyM3QK$' ${tf}0; then
$PRINTF "$FAILED:\n"
echo "$CMD0 &" >&2
cat "${te}0" >&2
echo "$CMD1" >&2
cat "${te}1" >&2
cat "${tf}0" >&2
echo "Authorization string not in client request" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
else
$PRINTF "$OK\n"
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
numOK=$((numOK+1))
fi
kill $pid 2>/dev/null
wait
fi ;; # NUMCOND, feats
esac
PORT=$((PORT+1))
N=$((N+1))
################################################################################## ##################################################################################
#================================================================================= #=================================================================================
# here come tests that might affect your systems integrity. Put normal tests # here come tests that might affect your systems integrity. Put normal tests

View file

@ -29,6 +29,7 @@ const struct optdesc opt_proxyport = { "proxyport", NULL, OPT_PROXYPORT, GROUP_H
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_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 addrdesc addr_proxy_connect = { "proxy", 3, xioopen_proxy_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_HTTP|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<proxy-server>:<host>:<port>") }; const struct addrdesc addr_proxy_connect = { "proxy", 3, xioopen_proxy_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_HTTP|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<proxy-server>:<host>:<port>") };
@ -239,6 +240,50 @@ 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_PROXY_AUTHORIZATION, &proxyvars->authstring); retropt_string(opts, OPT_PROXY_AUTHORIZATION, &proxyvars->authstring);
retropt_string(opts, OPT_PROXY_AUTHORIZATION_FILE, &proxyvars->authfile);
if (proxyvars->authfile) {
int authfd;
off_t length;
ssize_t bytes;
/* if we have a file containing authentication credentials and they were also
provided on the command line, something is misspecified */
if (proxyvars->authstring) {
Error("Only one of options proxy-authorization and proxy-authorization-file allowed");
return STAT_NORETRY;
}
authfd = Open(proxyvars->authfile, O_RDONLY, 0);
if (authfd < 0) {
Error2("open(\"%s\", O_RDONLY): %s", proxyvars->authfile, strerror(errno));
return STAT_NORETRY;
}
/* go to the end of our proxy auth file to
figure out how long our proxy auth is */
if ((length = Lseek(authfd, 0, SEEK_END)) < 0) {
Error2("lseek(<%s>, 0, SEEK_END): %s",
proxyvars->authfile, strerror(errno));
return STAT_RETRYLATER;
}
proxyvars->authstring = Malloc(length+1);
/* go back to the beginning */
Lseek(authfd, 0, SEEK_SET);
/* read our proxy info from the file */
if ((bytes = Read(authfd, proxyvars->authstring, (size_t) length)) < 0) {
Error3("read(<%s>, , "F_Zu"): %s", proxyvars->authfile, length, strerror(errno));
free(proxyvars->authstring);
Close(authfd);
return STAT_NORETRY;
}
if (bytes < length) {
Error3("read(<%s>, , "F_Zu"): got only "F_Zu" bytes",
proxyvars->authfile, length, bytes);
Close(authfd);
return STAT_NORETRY;
}
proxyvars->authstring[bytes] = '\0'; /* string termination */
Close(authfd);
}
if (proxyvars->doresolve) { if (proxyvars->doresolve) {
/* currently we only resolve to IPv4 addresses. This is in accordance to /* currently we only resolve to IPv4 addresses. This is in accordance to

View file

@ -10,6 +10,7 @@ struct proxyvars {
bool ignorecr; bool ignorecr;
bool doresolve; bool doresolve;
char *authstring; char *authstring;
char *authfile;
char *targetaddr; /* name/address of host, in malloced string */ char *targetaddr; /* name/address of host, in malloced string */
uint16_t targetport; uint16_t targetport;
} ; } ;
@ -18,6 +19,7 @@ extern const struct optdesc opt_proxyport;
extern const struct optdesc opt_ignorecr; extern const struct optdesc opt_ignorecr;
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 addrdesc addr_proxy_connect; extern const struct addrdesc addr_proxy_connect;

View file

@ -1254,8 +1254,10 @@ const struct optname optionnames[] = {
#endif #endif
IF_PROXY ("proxy-auth", &opt_proxy_authorization) IF_PROXY ("proxy-auth", &opt_proxy_authorization)
IF_PROXY ("proxy-authorization", &opt_proxy_authorization) IF_PROXY ("proxy-authorization", &opt_proxy_authorization)
IF_PROXY ("proxy-authorization-file", &opt_proxy_authorization_file)
IF_PROXY ("proxy-resolve", &opt_proxy_resolve) IF_PROXY ("proxy-resolve", &opt_proxy_resolve)
IF_PROXY ("proxyauth", &opt_proxy_authorization) IF_PROXY ("proxyauth", &opt_proxy_authorization)
IF_PROXY ("proxyauthfile", &opt_proxy_authorization_file)
IF_PROXY ("proxyport", &opt_proxyport) IF_PROXY ("proxyport", &opt_proxyport)
#ifdef ECHOPRT #ifdef ECHOPRT
IF_TERMIOS("prterase", &opt_echoprt) IF_TERMIOS("prterase", &opt_echoprt)

View file

@ -573,6 +573,7 @@ enum e_optcode {
OPT_PROTOCOL_FAMILY, /* 1=PF_UNIX, 2=PF_INET, 10=PF_INET6 */ OPT_PROTOCOL_FAMILY, /* 1=PF_UNIX, 2=PF_INET, 10=PF_INET6 */
OPT_PROXYPORT, OPT_PROXYPORT,
OPT_PROXY_AUTHORIZATION, OPT_PROXY_AUTHORIZATION,
OPT_PROXY_AUTHORIZATION_FILE,
OPT_PROXY_RESOLVE, OPT_PROXY_RESOLVE,
#if HAVE_DEV_PTMX || HAVE_DEV_PTC #if HAVE_DEV_PTMX || HAVE_DEV_PTC
OPT_PTMX, OPT_PTMX,