From 910f635cececf329dd50aedb9f6e1a8fae4efb0c Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 2 Feb 2011 00:45:39 +0100 Subject: added support for TLS (in anon mode) to tcpflood --- ChangeLog | 1 + configure.ac | 1 + tests/Makefile.am | 6 ++- tests/tcpflood.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 130 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index e6667c52..66743ad0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ +- added support for TLS (in anon mode) to tcpflood - improved TLS error reporting - improved TLS startup (Diffie-Hellman bits do not need to be generated, as we do not support full anon key exchange -- we always need certs) diff --git a/configure.ac b/configure.ac index b1af0662..1cde5935 100644 --- a/configure.ac +++ b/configure.ac @@ -651,6 +651,7 @@ AC_ARG_ENABLE(gnutls, ) if test "x$enable_gnutls" = "xyes"; then PKG_CHECK_MODULES(GNUTLS, gnutls >= 1.4.0) + AC_DEFINE([ENABLE_GNUTLS], [1], [Indicator that GnuTLS is present]) fi AM_CONDITIONAL(ENABLE_GNUTLS, test x$enable_gnutls = xyes) AC_SUBST(GNUTLS_CFLAGS) diff --git a/tests/Makefile.am b/tests/Makefile.am index 44c1daa7..68e84d53 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -326,7 +326,11 @@ uxsockrcvr_SOURCES = uxsockrcvr.c uxsockrcvr_LDADD = $(SOL_LIBS) tcpflood_SOURCES = tcpflood.c -tcpflood_LDADD = $(SOL_LIBS) $(PTHREADS_LIBS) +tcpflood_CPPFLAGS = $(PTHREADS_CFLAGS) $(GNUTLS_CFLAGS) +tcpflood_LDADD = $(SOL_LIBS) $(PTHREADS_LIBS) $(GNUTLS_LIBS) +if ENABLE_GNUTLS +tcpflood_LDADD += -lgcrypt +endif syslog_caller_SOURCES = syslog_caller.c syslog_caller_LDADD = $(SOL_LIBS) diff --git a/tests/tcpflood.c b/tests/tcpflood.c index 7b376bdd..eb2259ec 100644 --- a/tests/tcpflood.c +++ b/tests/tcpflood.c @@ -48,6 +48,8 @@ * -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 * is configured!) + * -z private key file for TLS mode + * -Z cert (public key) file for TLS mode * * Part of the testbench for rsyslog. * @@ -85,6 +87,12 @@ #include #include #include +#include +#ifdef ENABLE_GNUTLS +# include +# include + GCRY_THREAD_OPTION_PTHREAD_IMPL; +#endif #define EXIT_FAILURE 1 #define INVALID_SOCKET -1 @@ -122,6 +130,13 @@ static long long batchsize = 100000000ll; static int waittime = 0; static int runMultithreaded = 0; /* run tests in multithreaded mode */ static int numThrds = 1; /* number of threads to use */ +static char *tlsCertFile = NULL; +static char *tlsKeyFile = NULL; + +#ifdef ENABLE_GNUTLS +static gnutls_session_t *sessArray; /* array of TLS sessions to use */ +static gnutls_certificate_credentials tlscred; +#endif /* variables for managing multi-threaded operations */ int runningThreads; /* number of threads currently running */ @@ -151,7 +166,12 @@ struct runstats { static int udpsock; /* socket for sending in UDP mode */ static struct sockaddr_in udpRcvr; /* remote receiver in UDP mode */ -static enum { TP_UDP, TP_TCP } transport = TP_TCP; +static enum { TP_UDP, TP_TCP, TP_TLS } transport = TP_TCP; + +/* forward definitions */ +static void initTLSSess(int); +static int sendTLS(int i, char *buf, int lenBuf); +static void closeTLSSess(int __attribute__((unused)) i); /* prepare send subsystem for UDP send */ static inline int @@ -234,6 +254,9 @@ int openConnections(void) if(bShowProgress) write(1, " open connections", sizeof(" open connections")-1); +# ifdef ENABLE_GNUTLS + sessArray = calloc(numConnections, sizeof(gnutls_session_t)); +# endif sockArray = calloc(numConnections, sizeof(int)); for(i = 0 ; i < numConnections ; ++i) { if(i % 10 == 0) { @@ -244,6 +267,9 @@ int openConnections(void) printf("error in trying to open connection i=%d\n", i); return 1; } + if(transport == TP_TLS) { + initTLSSess(i); + } } if(bShowProgress) { lenMsg = sprintf(msgBuf, "\r%5.5d open connections\n", i); @@ -268,7 +294,7 @@ void closeConnections(void) struct linger ling; char msgBuf[128]; - if(transport != TP_TCP) + if(transport == TP_UDP) return; if(bShowProgress) @@ -287,6 +313,8 @@ void closeConnections(void) ling.l_onoff = 1; ling.l_linger = 1; setsockopt(sockArray[i], SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)); + if(transport == TP_TLS) + closeTLSSess(i); close(sockArray[i]); } } @@ -409,6 +437,8 @@ int sendMessages(struct instdata *inst) lenSend = send(sockArray[socknum], buf, lenBuf, 0); } else if(transport == TP_UDP) { lenSend = sendto(udpsock, buf, lenBuf, 0, &udpRcvr, sizeof(udpRcvr)); + } else if(transport == TP_TLS) { + lenSend = sendTLS(socknum, buf, lenBuf); } if(lenSend != lenBuf) { printf("\r%5.5d\n", i); @@ -643,6 +673,79 @@ runTests(void) return 0; } +# if defined(ENABLE_GNUTLS) +#if 0 +static void logFunction(int __attribute__((unused)) level, const char *msg) { + printf("%s\n", msg); +} +#endif +/* global init GnuTLS + */ +static void +initTLS(void) +{ + int r; + + /* order of gcry_control and gnutls_global_init matters! */ + gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); + gnutls_global_init (); + /* DEV debugging: gnutls_global_set_log_function(logFunction); */ + /* DEV debugging: gnutls_global_set_log_level(9); */ + + r = gnutls_certificate_allocate_credentials(&tlscred); + if(r != GNUTLS_E_SUCCESS) { + /* I don't know why this works even in case of error... */ + gnutls_perror(r); + } + r = gnutls_certificate_set_x509_key_file(tlscred, tlsCertFile, tlsKeyFile, GNUTLS_X509_FMT_PEM); + if(r != GNUTLS_E_SUCCESS) { + /* I don't know why this works even in case of error... */ + gnutls_perror(r); + } +} + +static void +initTLSSess(int i) +{ + int r; + gnutls_init (sessArray + i, GNUTLS_CLIENT); + + /* Use default priorities */ + gnutls_set_default_priority(sessArray[i]); + + /* put our credentials to the current session */ + r = gnutls_credentials_set(sessArray[i], GNUTLS_CRD_CERTIFICATE, tlscred); + + gnutls_transport_set_ptr(sessArray[i], (gnutls_transport_ptr_t) sockArray[i]); + + /* Perform the TLS handshake */ + r = gnutls_handshake(sessArray[i]); + + if(r < 0) { + fprintf (stderr, "TLS Handshake failed\n"); + gnutls_perror(r); + exit(1); + } +} + +static int +sendTLS(int i, char *buf, int lenBuf) +{ + return gnutls_record_send(sessArray[i], buf, lenBuf); +} + +static void +closeTLSSess(int i) +{ + gnutls_bye(sessArray[i], GNUTLS_SHUT_RDWR); + gnutls_deinit(sessArray[i]); +} +# else /* NO TLS available */ +static void initTLS(void) {} +static void initTLSSess(int __attribute__((unused)) i) {} +static int sendTLS(int i, char *buf, int lenBuf) { return 0; } +static void closeTLSSess(int __attribute__((unused)) i) {} +# endif /* Run the test. * rgerhards, 2009-04-03 @@ -666,7 +769,7 @@ int main(int argc, char *argv[]) setvbuf(stdout, buf, _IONBF, 48); - while((opt = getopt(argc, argv, "b:ef:F:t:p:c:C:m:i:I:P:d:Dn:M:rsBR:S:T:XW:Y")) != -1) { + while((opt = getopt(argc, argv, "b:ef:F:t:p:c:C:m:i:I:P:d:Dn:M:rsBR:S:T:XW:YzZ")) != -1) { switch (opt) { case 'b': batchsize = atoll(optarg); break; @@ -725,8 +828,15 @@ int main(int argc, char *argv[]) transport = TP_UDP; } else if(!strcmp(optarg, "tcp")) { transport = TP_TCP; + } else if(!strcmp(optarg, "tls")) { +# if defined(ENABLE_GNUTLS) + transport = TP_TLS; +# else + fprintf(stderr, "compiled without TLS support!\n", optarg); + exit(1); +# endif } else { - fprintf(stderr, "unkonwn transport '%s'\n", optarg); + fprintf(stderr, "unknown transport '%s'\n", optarg); exit(1); } break; @@ -734,6 +844,10 @@ int main(int argc, char *argv[]) break; case 'Y': runMultithreaded = 1; break; + case 'z': tlsKeyFile = optarg; + break; + case 'Z': tlsCertFile = optarg; + break; default: printf("invalid option '%c' or value missing - terminating...\n", opt); exit (1); break; @@ -769,6 +883,10 @@ int main(int argc, char *argv[]) } } + if(transport == TP_TLS) { + initTLS(); + } + if(openConnections() != 0) { printf("error opening connections\n"); exit(1); @@ -781,7 +899,7 @@ int main(int argc, char *argv[]) closeConnections(); /* this is important so that we do not finish too early! */ - if(nConnDrops > 0) + if(nConnDrops > 0 && !bSilent) printf("-D option initiated %ld connection closures\n", nConnDrops); if(!bSilent) -- cgit