relp: Add support setting openssl configuration commands.

Add new configuration parameter tls.tlscfgcmd to omrelp and imrelp.
(Using relpSrvSetTlsConfigCmd and relpCltSetTlsConfigCmd)

OpenSSL Version 1.0.2 or higher is required for this feature.
A list of possible commands and their valid values can be found in the
documentation: https://www.openssl.org/docs/man1.0.2/man3/SSL_CONF_cmd.html

The setting can be single or multiline, each configuration command is
separated by linefeed (n). Command and value are separated by
equal sign (=). Here are a few samples:

tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2"

tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1
MinProtocol=TLSv1.2"

Add to new testcases for librelp and tlscfgcmd.

closes https://github.com/rsyslog/rsyslog/issues/3959
This commit is contained in:
Andre lorbach 2019-11-13 09:55:52 +01:00
parent 71561b0d7b
commit 2bd6c99cbe
9 changed files with 215 additions and 4 deletions

View File

@ -1476,11 +1476,17 @@ if test "x$enable_relp" = "xyes"; then
[AC_DEFINE([HAVE_RELPSRVSETLSTNADDR], [1], [Define if relpSrvSetLstnAddr exists.])])
AC_CHECK_FUNC([relpEngineSetTLSLibByName],
[AC_DEFINE([HAVE_RELPENGINESETTLSLIBBYNAME], [1], [Define if relpEngineSetTLSLibByName exists.])])
AC_CHECK_FUNC([relpSrvSetTlsConfigCmd],
[AC_DEFINE([HAVE_RELPENGINESETTLSCFGCMD], [1], [Define if relpSrvSetTlsConfigCmd exists.])])
AC_CHECK_FUNC([relpSrvSetTlsConfigCmd],
[HAVE_RELPENGINESETTLSCFGCMD=1])
CFLAGS="$save_CFLAGS"
LIBS="$save_LIBS"
fi
AM_CONDITIONAL(ENABLE_RELP, test x$enable_relp = xyes)
AM_CONDITIONAL([USE_RELPENGINESETTLSCFGCMD], [test "x$HAVE_RELPENGINESETTLSCFGCMD" = x1])
# RELP default port
AC_ARG_ENABLE(omrelp-default-port,

View File

@ -96,6 +96,9 @@ struct instanceConf_s {
uchar *caCertFile;
uchar *myCertFile;
uchar *myPrivKeyFile;
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
uchar *tlscfgcmd;
#endif
int iKeepAliveIntvl;
int iKeepAliveProbes;
int iKeepAliveTime;
@ -162,6 +165,7 @@ static struct cnfparamdescr inppdescr[] = {
{ "tls.cacert", eCmdHdlrString, 0 },
{ "tls.mycert", eCmdHdlrString, 0 },
{ "tls.myprivkey", eCmdHdlrString, 0 },
{ "tls.tlscfgcmd", eCmdHdlrString, 0 },
{ "tls.compression", eCmdHdlrBinary, 0 }
};
static struct cnfparamblk inppblk =
@ -291,6 +295,9 @@ createInstance(instanceConf_t **pinst)
inst->caCertFile = NULL;
inst->myCertFile = NULL;
inst->myPrivKeyFile = NULL;
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
inst->tlscfgcmd = NULL;
#endif
inst->maxDataSize = 0;
inst->flowCtlType = eFLOWCTL_LIGHT_DELAY;
#ifdef HAVE_RELPSRVSETOVERSIZEMODE
@ -459,6 +466,12 @@ addListner(modConfData_t __attribute__((unused)) *modConf, instanceConf_t *inst)
ABORT_FINALIZE(RS_RET_RELP_ERR);
if(relpSrvSetPrivKey(pSrv, (char*) inst->myPrivKeyFile) != RELP_RET_OK)
ABORT_FINALIZE(RS_RET_RELP_ERR);
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
if (inst->tlscfgcmd != NULL) {
if(relpSrvSetTlsConfigCmd(pSrv, (char*) inst->tlscfgcmd) != RELP_RET_OK)
ABORT_FINALIZE(RS_RET_RELP_ERR);
}
#endif
for(i = 0 ; i < inst->permittedPeers.nmemb ; ++i) {
relpSrvAddPermittedPeer(pSrv, (char*)inst->permittedPeers.name[i]);
}
@ -618,6 +631,13 @@ CODESTARTnewInpInst
} else {
fclose(fp);
}
} else if(!strcmp(inppblk.descr[i].name, "tls.tlscfgcmd")) {
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
inst->tlscfgcmd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
#else
parser_errmsg("imrelp: librelp does not support input parameter 'tls.tlscfgcmd'; "
"it probably is too old (1.5.0 or higher should be fine); ignoring setting now.");
#endif
} else if(!strcmp(inppblk.descr[i].name, "tls.permittedpeer")) {
inst->permittedPeers.nmemb = pvals[i].val.d.ar->nmemb;
CHKmalloc(inst->permittedPeers.name =

View File

@ -88,6 +88,9 @@ typedef struct _instanceData {
uchar *caCertFile;
uchar *myCertFile;
uchar *myPrivKeyFile;
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
uchar *tlscfgcmd;
#endif
uchar *tplName;
uchar *localClientIP;
struct {
@ -140,6 +143,7 @@ static struct cnfparamdescr actpdescr[] = {
{ "tls.mycert", eCmdHdlrString, 0 },
{ "tls.myprivkey", eCmdHdlrString, 0 },
{ "tls.authmode", eCmdHdlrString, 0 },
{ "tls.tlscfgcmd", eCmdHdlrString, 0 },
{ "tls.permittedpeer", eCmdHdlrArray, 0 },
{ "port", eCmdHdlrGetWord, 0 },
{ "rebindinterval", eCmdHdlrInt, 0 },
@ -258,6 +262,12 @@ doCreateRelpClient(instanceData *pData, relpClt_t **pRelpClt)
ABORT_FINALIZE(RS_RET_RELP_ERR);
if(relpCltSetPrivKey(*pRelpClt, (char*) pData->myPrivKeyFile) != RELP_RET_OK)
ABORT_FINALIZE(RS_RET_RELP_ERR);
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
if (pData->tlscfgcmd != NULL) {
if(relpCltSetTlsConfigCmd(*pRelpClt, (char*) pData->tlscfgcmd) != RELP_RET_OK)
ABORT_FINALIZE(RS_RET_RELP_ERR);
}
#endif
for(i = 0 ; i < pData->permittedPeers.nmemb ; ++i) {
relpCltAddPermittedPeer(*pRelpClt, (char*)pData->permittedPeers.name[i]);
}
@ -305,6 +315,9 @@ CODESTARTcreateInstance
pData->caCertFile = NULL;
pData->myCertFile = NULL;
pData->myPrivKeyFile = NULL;
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
pData->tlscfgcmd = NULL;
#endif
pData->permittedPeers.nmemb = 0;
ENDcreateInstance
@ -330,6 +343,9 @@ CODESTARTfreeInstance
free(pData->caCertFile);
free(pData->myCertFile);
free(pData->myPrivKeyFile);
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
free(pData->tlscfgcmd);
#endif
if(pData->permittedPeers.name != NULL) {
for(i = 0 ; i < pData->permittedPeers.nmemb ; ++i) {
free(pData->permittedPeers.name[i]);
@ -364,6 +380,9 @@ setInstParamDefaults(instanceData *pData)
pData->caCertFile = NULL;
pData->myCertFile = NULL;
pData->myPrivKeyFile = NULL;
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
pData->tlscfgcmd = NULL;
#endif
pData->permittedPeers.name = NULL;
pData->permittedPeers.nmemb = 0;
}
@ -498,6 +517,14 @@ CODESTARTnewActInst
} else {
fclose(fp);
}
} else if(!strcmp(actpblk.descr[i].name, "tls.tlscfgcmd")) {
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
pData->tlscfgcmd = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
#else
LogError(0, RS_RET_NOT_IMPLEMENTED, "omrelp: librelp does not support input parameter "
"'tls.tlscfgcmd'; it probably is too old (1.5.0 or higher should be fine); "
"ignoring setting now.");
#endif
} else if(!strcmp(actpblk.descr[i].name, "tls.authmode")) {
pData->authmode = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL);
} else if(!strcmp(actpblk.descr[i].name, "tls.permittedpeer")) {
@ -512,7 +539,7 @@ CODESTARTnewActInst
"param '%s'\n", actpblk.descr[i].name);
}
}
CODE_STD_STRING_REQUESTnewActInst(1)
CHKiRet(OMSRsetEntry(*ppOMSR, 0, (uchar*)strdup((pData->tplName == NULL) ?
@ -736,7 +763,7 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
*(pData->port + i) = '\0';
}
}
/* now skip to template */
bErr = 0;
while(*p && *p != ';') {

View File

@ -47,6 +47,7 @@ check_PROGRAMS = $(TESTRUNS) ourtail tcpflood chkseq msleep randomgen \
mangle_qi \
have_relpSrvSetOversizeMode \
have_relpEngineSetTLSLibByName \
have_relpSrvSetTlsConfigCmd \
test_id
if ENABLE_JOURNAL_TESTS
if ENABLE_IMJOURNAL
@ -1206,6 +1207,11 @@ TESTS += \
relp_tls_certificate_not_found.sh \
omrelp_wrong_authmode.sh \
imrelp-tls.sh
if USE_RELPENGINESETTLSCFGCMD
TESTS += \
imrelp-tls-cfgcmd.sh \
sndrcv_relp_tls-cfgcmd.sh
endif # USE_RELPENGINESETTLSCFGCMD
endif # ENABLE_GNUTLS
if HAVE_VALGRIND
TESTS += \
@ -2040,6 +2046,8 @@ EXTRA_DIST= \
relp_tls_certificate_not_found.sh \
omrelp_wrong_authmode.sh \
imrelp-tls.sh \
imrelp-tls-cfgcmd.sh \
sndrcv_relp_tls-cfgcmd.sh \
sndrcv_relp_dflt_pt.sh \
sndrcv_udp.sh \
imudp_thread_hang.sh \
@ -2513,6 +2521,7 @@ mangle_qi_SOURCES = mangle_qi.c
chkseq_SOURCES = chkseq.c
have_relpSrvSetOversizeMode = have_relpSrvSetOversizeMode.c
have_relpEngineSetTLSLibByName = have_relpEngineSetTLSLibByName.c
have_relpSrvSetTlsConfigCmd = have_relpSrvSetTlsConfigCmd.c
test_id_SOURCES = test_id.c
uxsockrcvr_SOURCES = uxsockrcvr.c

View File

@ -1188,6 +1188,14 @@ error_exit() {
thread apply all bt full
q
EOF
$SUDO gdb ./tcpflood "$CORE" -batch <<- EOF
bt
echo === THREAD INFO ===
info thread
echo === thread apply all bt full ===
thread apply all bt full
q
EOF
fi
fi
if [[ ! -e IN_AUTO_DEBUG && "$USE_AUTO_DEBUG" == 'on' ]]; then

View File

@ -0,0 +1,10 @@
#include "config.h"
int main(int argc __attribute__((unused)), char *argv[]__attribute__((unused)))
{
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
return 0;
#else
return 1;
#endif
}

47
tests/imrelp-tls-cfgcmd.sh Executable file
View File

@ -0,0 +1,47 @@
#!/bin/bash
# addd 2019-11-14 by alorbach, released under ASL 2.0
. ${srcdir:=.}/diag.sh init
export NUMMESSAGES=1000
export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
generate_conf
add_conf '
module( load="../plugins/imrelp/.libs/imrelp"
tls.tlslib="openssl")
input(type="imrelp" port="'$TCPFLOOD_PORT'" tls="on"
tls.cacert="'$srcdir'/tls-certs/ca.pem"
tls.mycert="'$srcdir'/tls-certs/cert.pem"
tls.myprivkey="'$srcdir'/tls-certs/key.pem"
tls.authmode="certvalid"
tls.permittedpeer="rsyslog"
tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2")
template(name="outfmt" type="string" string="%msg:F,58:2%\n")
:msg, contains, "msgnum:" action(type="omfile" template="outfmt"
file=`echo $RSYSLOG_OUT_LOG`)
'
startup
tcpflood --check-only -k "Protocol=-ALL,TLSv1.2" -u "openssl" -Trelp-tls -acertvalid -p$TCPFLOOD_PORT -m$NUMMESSAGES -x "$srcdir/tls-certs/ca.pem" -z "$srcdir/tls-certs/key.pem" -Z "$srcdir/tls-certs/cert.pem" -Ersyslog 2> ${RSYSLOG_DYNNAME}.tcpflood
shutdown_when_empty
wait_shutdown
content_check --check-only "parameter tls.tlslib ignored" ${RSYSLOG_DEBUGLOG}
ret=$?
if [ $ret == 0 ]; then
echo "SKIP: Parameter tls.tlslib not supported"
skip_test
else
content_check --check-only "OpenSSL Version too old" ${RSYSLOG_DEBUGLOG}
ret=$?
if [ $ret == 0 ]; then
echo "SKIP: OpenSSL Version too old"
skip_test
else
# Kindly check for a failed session
content_check "relp connect failed with return 10031" ${RSYSLOG_DYNNAME}.tcpflood
fi
fi
exit_test

61
tests/sndrcv_relp_tls-cfgcmd.sh Executable file
View File

@ -0,0 +1,61 @@
#!/bin/bash
# added 2019-11-13 by alorbach
. ${srcdir:=.}/diag.sh init
export PORT_RCVR="$(get_free_port)"
export RSYSLOG_DEBUG="debug nologfuncflow noprintmutexaction nostdout"
export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.receiver.debuglog"
generate_conf
add_conf '
module( load="../plugins/imrelp/.libs/imrelp"
tls.tlslib="openssl")
# then SENDER sends to this port (not tcpflood!)
input( type="imrelp" port="'$PORT_RCVR'" tls="on"
tls.tlscfgcmd="Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.2"
)
$template outfmt,"%msg:F,58:2%\n"
:msg, contains, "msgnum:" action(type="omfile" file="'$RSYSLOG_OUT_LOG'" template="outfmt")
'
startup
export RSYSLOG_DEBUGLOG="$RSYSLOG_DYNNAME.sender.debuglog"
generate_conf 2
add_conf '
module( load="../plugins/omrelp/.libs/omrelp"
tls.tlslib="openssl")
action( type="omrelp" target="127.0.0.1" port="'$PORT_RCVR'" tls="on"
tls.tlscfgcmd="Protocol=-ALL,TLSv1.2" )
' 2
startup 2
# now inject the messages into instance 2. It will connect to instance 1,
# and that instance will record the data.
injectmsg2 1 1000
# shut down sender
shutdown_when_empty 2
wait_shutdown 2
# now it is time to stop the receiver as well
shutdown_when_empty
wait_shutdown
content_check --check-only "parameter tls.tlslib ignored" ${RSYSLOG_DEBUGLOG}
ret=$?
if [ $ret == 0 ]; then
echo "SKIP: Parameter tls.tlslib not supported"
skip_test
else
content_check --check-only "OpenSSL Version too old" $RSYSLOG_DEBUGLOG
ret=$?
if [ $ret == 0 ]; then
echo "SKIP: OpenSSL Version too old"
skip_test
else
# Kindly check for a failed session
content_check "librelp error 10031" $RSYSLOG_DEBUGLOG
# content_check "OpenSSL Error Stack:"
fi
fi
exit_test

View File

@ -53,6 +53,7 @@
* Average,min,max
* -T transport to use. Currently supported: "udp", "tcp" (default), "tls" (tcp+tls), relp-plain, relp-tls
* Note: UDP supports a single target port, only
* -u Set RELP TLS Library to gnutls or openssl
* -W wait time between sending batches of messages, in microseconds (Default: 0)
* -b number of messages within a batch (default: 100,000,000 millions)
* -Y use multiple threads, one per connection (which means 1 if one only connection
@ -72,6 +73,7 @@
* Currently only OpenSSL is supported, possible configuration commands and values can be found here:
* https://www.openssl.org/docs/man1.0.2/man3/SSL_CONF_cmd.html
* Sample: -k"Protocol=ALL,-SSLv2,-SSLv3,-TLSv1,-TLSv1.1"
* Works for LIBRELP now as well!
*
* Part of the testbench for rsyslog.
*
@ -210,6 +212,10 @@ static char *tlsCertFile = NULL;
static char *tlsKeyFile = NULL;
static char *relpAuthMode = NULL;
static char *relpPermittedPeer = NULL;
#if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
static char *relpTlsLib = NULL;
#endif
static int tlsLogLevel = 0;
static char *jsonCookie = NULL; /* if non-NULL, use JSON format with this cookie */
static int octateCountFramed = 0;
@ -328,6 +334,11 @@ int openConn(int *fd, const int connIdx)
snprintf(relpPort, sizeof(relpPort), "%d", port);
CHKRELP(relpEngineCltConstruct(pRelpEngine, &relpClt));
if(transport == TP_RELP_TLS) {
#if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
if(relpTlsLib != NULL && relpEngineSetTLSLibByName(pRelpEngine, relpTlsLib) != RELP_RET_OK) {
fprintf(stderr, "relpTlsLib not accepted by librelp, using default\n");
}
#endif
if(relpCltEnableTLS(relpClt) != RELP_RET_OK) {
fprintf(stderr, "error while enabling TLS for relp\n");
exit(1);
@ -353,6 +364,14 @@ int openConn(int *fd, const int connIdx)
fprintf(stderr, "could not set Permitted Peer: %s\n", relpPermittedPeer);
exit(1);
}
#if defined(HAVE_RELPENGINESETTLSCFGCMD)
/* Check for Custom Config string */
if(customConfig != NULL && relpCltSetTlsConfigCmd(relpClt, customConfig)
!= RELP_RET_OK) {
fprintf(stderr, "could not set custom tls command: %s\n", customConfig);
exit(1);
}
#endif
}
relpCltArray[connIdx] = relpClt;
relp_r = relpCltConnect(relpCltArray[connIdx], 2,
@ -1237,7 +1256,6 @@ initTLS(void)
#else
printf("tcpflood: error, OpenSSL Version too old, SSL_CONF_cmd API is not supported.");
#endif
}
@ -1553,7 +1571,7 @@ int main(int argc, char *argv[])
setvbuf(stdout, buf, _IONBF, 48);
while((opt = getopt(argc, argv, "a:Bb:c:C:d:DeE:f:F:k:i:I:l:j:L:m:M:n:OP:p:rR:sS:t:T:vW:x:XyYz:Z:")) != -1) {
while((opt = getopt(argc, argv, "a:Bb:c:C:d:DeE:f:F:i:I:j:k:l:L:m:M:n:OP:p:rR:sS:t:T:u:vW:x:XyYz:Z:")) != -1) {
switch (opt) {
case 'b': batchsize = atoll(optarg);
break;
@ -1663,6 +1681,11 @@ int main(int argc, char *argv[])
break;
case 'E': relpPermittedPeer = optarg;
break;
case 'u':
#if defined(HAVE_RELPENGINESETTLSLIBBYNAME)
relpTlsLib = optarg;
#endif
break;
case 'W': waittime = atoi(optarg);
break;
case 'Y': runMultithreaded = 1;