diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..e7b0f7e51 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,38 @@ +language: c + +compiler: + - gcc + - clang + +before_install: + - sudo apt-get update -qq + - sudo apt-get install -qq bison flex gperf gettext + - ./scripts/test.sh deps + +script: + - ./autogen.sh + - ./scripts/test.sh + +env: + global: + - TESTS_REDUCED_KEYLENGTHS=yes + - LEAK_DETECTIVE=no + - MONOLITHIC=no + matrix: + - TEST=default + - TEST=default MONOLITHIC=yes + - TEST=default LEAK_DETECTIVE=yes + - TEST=openssl + - TEST=openssl LEAK_DETECTIVE=yes + # libgcrypt can't be deinitialized so we can't test it with leak detective + - TEST=gcrypt + # we can't test Vstr as negative int args are not properly passed to CBs + - TEST=printf-builtin + - TEST=printf-builtin LEAK_DETECTIVE=yes + - TEST=all + - TEST=all MONOLITHIC=yes + +matrix: + include: + - compiler: gcc + env: TEST=dist diff --git a/configure.ac b/configure.ac index e4d5bc17a..568b9e2cd 100644 --- a/configure.ac +++ b/configure.ac @@ -66,6 +66,7 @@ ARG_WITH_SET([tss], [no], [set implementation of the Trusted Co ARG_WITH_SET([capabilities], [no], [set capability dropping library. Currently supported values are "libcap" and "native"]) ARG_WITH_SET([mpz_powm_sec], [yes], [use the more side-channel resistant mpz_powm_sec in libgmp, if available]) ARG_WITH_SET([dev-headers], [no], [install strongSwan development headers to directory.]) +ARG_WITH_SET([printf-hooks], [auto], [force the use of a specific printf hook implementation (auto, builtin, glibc, vstr).]) if test -n "$PKG_CONFIG"; then systemdsystemunitdir_default=$($PKG_CONFIG --variable=systemdsystemunitdir systemd) @@ -118,53 +119,56 @@ AC_SUBST(ipsec_script_upper, [`echo -n "$ipsec_script" | tr a-z A-Z`]) m4_include(m4/macros/enable-disable.m4) -ARG_ENABL_SET([curl], [enable CURL fetcher plugin to fetch files via libcurl. Requires libcurl.]) -ARG_ENABL_SET([unbound], [enable UNBOUND resolver plugin to perform DNS queries via libunbound. Requires libldns and libunbound.]) -ARG_ENABL_SET([soup], [enable soup fetcher plugin to fetch from HTTP via libsoup. Requires libsoup.]) -ARG_ENABL_SET([ldap], [enable LDAP fetching plugin to fetch files via libldap. Requires openLDAP.]) +# crypto plugins ARG_DISBL_SET([aes], [disable AES software implementation plugin.]) -ARG_DISBL_SET([des], [disable DES/3DES software implementation plugin.]) +ARG_ENABL_SET([af-alg], [enable AF_ALG crypto interface to Linux Crypto API.]) ARG_ENABL_SET([blowfish], [enable Blowfish software implementation plugin.]) -ARG_DISBL_SET([rc2], [disable RC2 software implementation plugin.]) +ARG_ENABL_SET([ccm], [enables the CCM AEAD wrapper crypto plugin.]) +ARG_DISBL_SET([cmac], [disable CMAC crypto implementation plugin.]) +ARG_ENABL_SET([ctr], [enables the Counter Mode wrapper crypto plugin.]) +ARG_DISBL_SET([des], [disable DES/3DES software implementation plugin.]) +ARG_DISBL_SET([fips-prf], [disable FIPS PRF software implementation plugin.]) +ARG_ENABL_SET([gcm], [enables the GCM AEAD wrapper crypto plugin.]) +ARG_ENABL_SET([gcrypt], [enables the libgcrypt plugin.]) +ARG_DISBL_SET([gmp], [disable GNU MP (libgmp) based crypto implementation plugin.]) +ARG_DISBL_SET([hmac], [disable HMAC crypto implementation plugin.]) ARG_ENABL_SET([md4], [enable MD4 software implementation plugin.]) ARG_DISBL_SET([md5], [disable MD5 software implementation plugin.]) +ARG_DISBL_SET([nonce], [disable nonce generation plugin.]) +ARG_ENABL_SET([ntru], [enables the NTRU crypto plugin.]) +ARG_ENABL_SET([openssl], [enables the OpenSSL crypto plugin.]) +ARG_ENABL_SET([padlock], [enables VIA Padlock crypto plugin.]) +ARG_DISBL_SET([random], [disable RNG implementation on top of /dev/(u)random.]) +ARG_DISBL_SET([rc2], [disable RC2 software implementation plugin.]) +ARG_ENABL_SET([rdrand], [enable Intel RDRAND random generator plugin.]) ARG_DISBL_SET([sha1], [disable SHA1 software implementation plugin.]) ARG_DISBL_SET([sha2], [disable SHA256/SHA384/SHA512 software implementation plugin.]) -ARG_DISBL_SET([fips-prf], [disable FIPS PRF software implementation plugin.]) -ARG_DISBL_SET([gmp], [disable GNU MP (libgmp) based crypto implementation plugin.]) -ARG_ENABL_SET([rdrand], [enable Intel RDRAND random generator plugin.]) -ARG_DISBL_SET([random], [disable RNG implementation on top of /dev/(u)random.]) -ARG_DISBL_SET([nonce], [disable nonce generation plugin.]) -ARG_DISBL_SET([x509], [disable X509 certificate implementation plugin.]) -ARG_DISBL_SET([revocation], [disable X509 CRL/OCSP revocation check plugin.]) -ARG_DISBL_SET([constraints], [disable advanced X509 constraint checking plugin.]) -ARG_DISBL_SET([pubkey], [disable RAW public key support plugin.]) +ARG_DISBL_SET([xcbc], [disable xcbc crypto implementation plugin.]) +# encoding/decoding plugins +ARG_DISBL_SET([dnskey], [disable DNS RR key decoding plugin.]) +ARG_DISBL_SET([pem], [disable PEM decoding plugin.]) +ARG_DISBL_SET([pgp], [disable PGP key decoding plugin.]) ARG_DISBL_SET([pkcs1], [disable PKCS1 key decoding plugin.]) ARG_DISBL_SET([pkcs7], [disable PKCS7 container support plugin.]) ARG_DISBL_SET([pkcs8], [disable PKCS8 private key decoding plugin.]) ARG_DISBL_SET([pkcs12], [disable PKCS12 container support plugin.]) -ARG_DISBL_SET([pgp], [disable PGP key decoding plugin.]) -ARG_DISBL_SET([dnskey], [disable DNS RR key decoding plugin.]) +ARG_DISBL_SET([pubkey], [disable RAW public key support plugin.]) ARG_DISBL_SET([sshkey], [disable SSH key decoding plugin.]) -ARG_ENABL_SET([dnscert], [enable DNSCERT authentication plugin.]) -ARG_ENABL_SET([ipseckey], [enable IPSECKEY authentication plugin.]) -ARG_DISBL_SET([pem], [disable PEM decoding plugin.]) -ARG_DISBL_SET([hmac], [disable HMAC crypto implementation plugin.]) -ARG_DISBL_SET([cmac], [disable CMAC crypto implementation plugin.]) -ARG_DISBL_SET([xcbc], [disable xcbc crypto implementation plugin.]) -ARG_ENABL_SET([af-alg], [enable AF_ALG crypto interface to Linux Crypto API.]) -ARG_ENABL_SET([test-vectors], [enable plugin providing crypto test vectors.]) +ARG_DISBL_SET([x509], [disable X509 certificate implementation plugin.]) +# fetcher/resolver plugins +ARG_ENABL_SET([curl], [enable CURL fetcher plugin to fetch files via libcurl. Requires libcurl.]) +ARG_ENABL_SET([ldap], [enable LDAP fetching plugin to fetch files via libldap. Requires openLDAP.]) +ARG_ENABL_SET([soup], [enable soup fetcher plugin to fetch from HTTP via libsoup. Requires libsoup.]) +ARG_ENABL_SET([unbound], [enable UNBOUND resolver plugin to perform DNS queries via libunbound. Requires libldns and libunbound.]) +# database plugins ARG_ENABL_SET([mysql], [enable MySQL database support. Requires libmysqlclient_r.]) ARG_ENABL_SET([sqlite], [enable SQLite database support. Requires libsqlite3.]) -ARG_DISBL_SET([stroke], [disable charons stroke configuration backend.]) -ARG_ENABL_SET([medsrv], [enable mediation server web frontend and daemon plugin.]) -ARG_ENABL_SET([medcli], [enable mediation client configuration database plugin.]) -ARG_ENABL_SET([smp], [enable SMP configuration and control interface. Requires libxml.]) -ARG_ENABL_SET([sql], [enable SQL database configuration backend.]) -ARG_ENABL_SET([leak-detective], [enable malloc hooks to find memory leaks.]) -ARG_ENABL_SET([lock-profiler], [enable lock/mutex profiling code.]) -ARG_ENABL_SET([unit-tester], [enable unit tests on IKEv2 daemon startup.]) -ARG_ENABL_SET([load-tester], [enable load testing plugin for IKEv2 daemon.]) +# authentication/credential plugins +ARG_ENABL_SET([addrblock], [enables RFC 3779 address block constraint support.]) +ARG_ENABL_SET([agent], [enables the ssh-agent signing plugin.]) +ARG_DISBL_SET([constraints], [disable advanced X509 constraint checking plugin.]) +ARG_ENABL_SET([coupling], [enable IKEv2 plugin to couple peer certificates permanently to authentication.]) +ARG_ENABL_SET([dnscert], [enable DNSCERT authentication plugin.]) ARG_ENABL_SET([eap-sim], [enable SIM authentication module for EAP.]) ARG_ENABL_SET([eap-sim-file], [enable EAP-SIM backend based on a triplet file.]) ARG_ENABL_SET([eap-sim-pcsc], [enable EAP-SIM backend based on a smartcard reader. Requires libpcsclite.]) @@ -183,17 +187,37 @@ ARG_ENABL_SET([eap-peap], [enable EAP PEAP authentication module.]) ARG_ENABL_SET([eap-tnc], [enable EAP TNC trusted network connect module.]) ARG_ENABL_SET([eap-dynamic], [enable dynamic EAP proxy module.]) ARG_ENABL_SET([eap-radius], [enable RADIUS proxy authentication module.]) +ARG_ENABL_SET([ipseckey], [enable IPSECKEY authentication plugin.]) +ARG_ENABL_SET([keychain], [enables OS X Keychain Services credential set.]) +ARG_ENABL_SET([pkcs11], [enables the PKCS11 token support plugin.]) +ARG_DISBL_SET([revocation], [disable X509 CRL/OCSP revocation check plugin.]) +ARG_ENABL_SET([whitelist], [enable peer identity whitelisting plugin.]) ARG_DISBL_SET([xauth-generic], [disable generic XAuth backend.]) ARG_ENABL_SET([xauth-eap], [enable XAuth backend using EAP methods to verify passwords.]) ARG_ENABL_SET([xauth-pam], [enable XAuth backend using PAM to verify passwords.]) ARG_ENABL_SET([xauth-noauth], [enable XAuth pseudo-backend that does not actually verify or even request any credentials.]) -ARG_ENABL_SET([tnc-ifmap], [enable TNC IF-MAP module. Requires libxml]) -ARG_ENABL_SET([tnc-pdp], [enable TNC policy decision point module.]) -ARG_ENABL_SET([tnc-imc], [enable TNC IMC module.]) -ARG_ENABL_SET([tnc-imv], [enable TNC IMV module.]) -ARG_ENABL_SET([tnccs-11], [enable TNCCS 1.1 protocol module. Requires libxml]) -ARG_ENABL_SET([tnccs-20], [enable TNCCS 2.0 protocol module.]) -ARG_ENABL_SET([tnccs-dynamic], [enable dynamic TNCCS protocol discovery module.]) +# kernel interfaces / sockets +ARG_DISBL_SET([kernel-netlink], [disable the netlink kernel interface.]) +ARG_ENABL_SET([kernel-pfkey], [enable the PF_KEY kernel interface.]) +ARG_ENABL_SET([kernel-pfroute], [enable the PF_ROUTE kernel interface.]) +ARG_ENABL_SET([kernel-klips], [enable the KLIPS kernel interface.]) +ARG_ENABL_SET([kernel-libipsec],[enable the libipsec kernel interface.]) +ARG_DISBL_SET([socket-default], [disable default socket implementation for charon.]) +ARG_ENABL_SET([socket-dynamic], [enable dynamic socket implementation for charon]) +# configuration/control plugins +ARG_DISBL_SET([stroke], [disable charons stroke configuration backend.]) +ARG_ENABL_SET([smp], [enable SMP configuration and control interface. Requires libxml.]) +ARG_ENABL_SET([sql], [enable SQL database configuration backend.]) +ARG_ENABL_SET([uci], [enable OpenWRT UCI configuration plugin.]) +# attribute provider/consumer plugins +ARG_ENABL_SET([android-dns], [enable Android specific DNS handler.]) +ARG_DISBL_SET([attr], [disable strongswan.conf based configuration attribute plugin.]) +ARG_ENABL_SET([attr-sql], [enable SQL based configuration attribute plugin.]) +ARG_ENABL_SET([dhcp], [enable DHCP based attribute provider plugin.]) +ARG_ENABL_SET([osx-attr], [enable OS X SystemConfiguration attribute handler.]) +ARG_DISBL_SET([resolve], [disable resolve DNS handler plugin.]) +ARG_ENABL_SET([unity], [enables Cisco Unity extension plugin.]) +# TNC modules/plugins ARG_ENABL_SET([imc-test], [enable IMC test module.]) ARG_ENABL_SET([imv-test], [enable IMV test module.]) ARG_ENABL_SET([imc-scanner], [enable IMC port scanner module.]) @@ -204,67 +228,56 @@ ARG_ENABL_SET([imc-attestation],[enable IMC attestation module.]) ARG_ENABL_SET([imv-attestation],[enable IMV attestation module.]) ARG_ENABL_SET([imc-swid], [enable IMC swid module.]) ARG_ENABL_SET([imv-swid], [enable IMV swid module.]) -ARG_DISBL_SET([kernel-netlink], [disable the netlink kernel interface.]) -ARG_ENABL_SET([kernel-pfkey], [enable the PF_KEY kernel interface.]) -ARG_ENABL_SET([kernel-pfroute], [enable the PF_ROUTE kernel interface.]) -ARG_ENABL_SET([kernel-klips], [enable the KLIPS kernel interface.]) -ARG_ENABL_SET([kernel-libipsec],[enable the libipsec kernel interface.]) -ARG_ENABL_SET([libipsec], [enable user space IPsec implementation.]) -ARG_DISBL_SET([socket-default], [disable default socket implementation for charon.]) -ARG_ENABL_SET([socket-dynamic], [enable dynamic socket implementation for charon]) +ARG_ENABL_SET([tnc-ifmap], [enable TNC IF-MAP module. Requires libxml]) +ARG_ENABL_SET([tnc-imc], [enable TNC IMC module.]) +ARG_ENABL_SET([tnc-imv], [enable TNC IMV module.]) +ARG_ENABL_SET([tnc-pdp], [enable TNC policy decision point module.]) +ARG_ENABL_SET([tnccs-11], [enable TNCCS 1.1 protocol module. Requires libxml]) +ARG_ENABL_SET([tnccs-20], [enable TNCCS 2.0 protocol module.]) +ARG_ENABL_SET([tnccs-dynamic], [enable dynamic TNCCS protocol discovery module.]) +# misc plugins +ARG_ENABL_SET([android-log], [enable Android specific logger plugin.]) +ARG_ENABL_SET([certexpire], [enable CSV export of expiration dates of used certificates.]) +ARG_ENABL_SET([duplicheck], [advanced duplicate checking plugin using liveness checks.]) +ARG_ENABL_SET([error-notify], [enable error notification plugin.]) ARG_ENABL_SET([farp], [enable ARP faking plugin that responds to ARP requests to peers virtual IP]) +ARG_ENABL_SET([ha], [enable high availability cluster plugin.]) +ARG_ENABL_SET([led], [enable plugin to control LEDs on IKEv2 activity using the Linux kernel LED subsystem.]) +ARG_ENABL_SET([load-tester], [enable load testing plugin for IKEv2 daemon.]) +ARG_ENABL_SET([lookip], [enable fast virtual IP lookup and notification plugin.]) +ARG_ENABL_SET([maemo], [enable Maemo specific plugin.]) +ARG_ENABL_SET([radattr], [enable plugin to inject and process custom RADIUS attributes as IKEv2 client.]) +ARG_ENABL_SET([systime-fix], [enable plugin to handle cert lifetimes with invalid system time gracefully.]) +ARG_ENABL_SET([test-vectors], [enable plugin providing crypto test vectors.]) +ARG_ENABL_SET([unit-tester], [enable unit tests on IKEv2 daemon startup.]) +ARG_DISBL_SET([updown], [disable updown firewall script plugin.]) +# programs/components +ARG_DISBL_SET([charon], [disable the IKEv1/IKEv2 keying daemon charon.]) +ARG_ENABL_SET([cmd], [enable the command line IKE client charon-cmd.]) +ARG_ENABL_SET([conftest], [enforce Suite B conformance test framework.]) ARG_ENABL_SET([dumm], [enable the DUMM UML test framework.]) ARG_ENABL_SET([fast], [enable libfast (FastCGI Application Server w/ templates.]) +ARG_ENABL_SET([libipsec], [enable user space IPsec implementation.]) ARG_ENABL_SET([manager], [enable web management console (proof of concept).]) -ARG_ENABL_SET([mediation], [enable IKEv2 Mediation Extension.]) -ARG_ENABL_SET([integrity-test], [enable integrity testing of libstrongswan and plugins.]) -ARG_DISBL_SET([load-warning], [disable the charon plugin load option warning in starter.]) +ARG_ENABL_SET([medcli], [enable mediation client configuration database plugin.]) +ARG_ENABL_SET([medsrv], [enable mediation server web frontend and daemon plugin.]) +ARG_ENABL_SET([nm], [enable NetworkManager backend.]) +ARG_DISBL_SET([scripts], [disable additional utilities (found in directory scripts).]) +ARG_ENABL_SET([tkm], [enable Trusted Key Manager support.]) +ARG_DISBL_SET([tools], [disable additional utilities (openac, scepclient and pki).]) +# optional features +ARG_ENABL_SET([bfd-backtraces], [use binutils libbfd to resolve backtraces for memory leaks and segfaults.]) ARG_DISBL_SET([ikev1], [disable IKEv1 protocol support in charon.]) ARG_DISBL_SET([ikev2], [disable IKEv2 protocol support in charon.]) -ARG_DISBL_SET([charon], [disable the IKEv1/IKEv2 keying daemon charon.]) -ARG_DISBL_SET([tools], [disable additional utilities (openac, scepclient and pki).]) -ARG_DISBL_SET([scripts], [disable additional utilities (found in directory scripts).]) -ARG_ENABL_SET([conftest], [enforce Suite B conformance test framework.]) -ARG_DISBL_SET([updown], [disable updown firewall script plugin.]) -ARG_DISBL_SET([attr], [disable strongswan.conf based configuration attribute plugin.]) -ARG_ENABL_SET([attr-sql], [enable SQL based configuration attribute plugin.]) -ARG_ENABL_SET([dhcp], [enable DHCP based attribute provider plugin.]) -ARG_DISBL_SET([resolve], [disable resolve DNS handler plugin.]) -ARG_ENABL_SET([padlock], [enables VIA Padlock crypto plugin.]) -ARG_ENABL_SET([openssl], [enables the OpenSSL crypto plugin.]) -ARG_ENABL_SET([gcrypt], [enables the libgcrypt plugin.]) -ARG_ENABL_SET([agent], [enables the ssh-agent signing plugin.]) -ARG_ENABL_SET([keychain], [enables OS X Keychain Services credential set.]) -ARG_ENABL_SET([pkcs11], [enables the PKCS11 token support plugin.]) -ARG_ENABL_SET([ctr], [enables the Counter Mode wrapper crypto plugin.]) -ARG_ENABL_SET([ccm], [enables the CCM AEAD wrapper crypto plugin.]) -ARG_ENABL_SET([gcm], [enables the GCM AEAD wrapper crypto plugin.]) -ARG_ENABL_SET([ntru], [enables the NTRU crypto plugin.]) -ARG_ENABL_SET([addrblock], [enables RFC 3779 address block constraint support.]) -ARG_ENABL_SET([unity], [enables Cisco Unity extension plugin.]) -ARG_ENABL_SET([uci], [enable OpenWRT UCI configuration plugin.]) -ARG_ENABL_SET([osx-attr], [enable OS X SystemConfiguration attribute handler.]) -ARG_ENABL_SET([android-dns], [enable Android specific DNS handler.]) -ARG_ENABL_SET([android-log], [enable Android specific logger plugin.]) -ARG_ENABL_SET([maemo], [enable Maemo specific plugin.]) -ARG_ENABL_SET([nm], [enable NetworkManager backend.]) -ARG_ENABL_SET([ha], [enable high availability cluster plugin.]) -ARG_ENABL_SET([whitelist], [enable peer identity whitelisting plugin.]) -ARG_ENABL_SET([lookip], [enable fast virtual IP lookup and notification plugin.]) -ARG_ENABL_SET([error-notify], [enable error notification plugin.]) -ARG_ENABL_SET([certexpire], [enable CSV export of expiration dates of used certificates.]) -ARG_ENABL_SET([systime-fix], [enable plugin to handle cert lifetimes with invalid system time gracefully.]) -ARG_ENABL_SET([led], [enable plugin to control LEDs on IKEv2 activity using the Linux kernel LED subsystem.]) -ARG_ENABL_SET([duplicheck], [advanced duplicate checking plugin using liveness checks.]) -ARG_ENABL_SET([coupling], [enable IKEv2 plugin to couple peer certificates permanently to authentication.]) -ARG_ENABL_SET([radattr], [enable plugin to inject and process custom RADIUS attributes as IKEv2 client.]) -ARG_ENABL_SET([vstr], [enforce using the Vstr string library to replace glibc-like printf hooks.]) -ARG_ENABL_SET([monolithic], [build monolithic version of libstrongswan that includes all enabled plugins. Similarly, the plugins of charon are assembled in libcharon.]) -ARG_ENABL_SET([bfd-backtraces], [use binutils libbfd to resolve backtraces for memory leaks and segfaults.]) +ARG_ENABL_SET([integrity-test], [enable integrity testing of libstrongswan and plugins.]) +ARG_DISBL_SET([load-warning], [disable the charon plugin load option warning in starter.]) +ARG_ENABL_SET([mediation], [enable IKEv2 Mediation Extension.]) ARG_ENABL_SET([unwind-backtraces],[use libunwind to create backtraces for memory leaks and segfaults.]) +# compile options ARG_ENABL_SET([coverage], [enable lcov coverage report generation.]) -ARG_ENABL_SET([tkm], [enable Trusted Key Manager support.]) -ARG_ENABL_SET([cmd], [enable the command line IKE client charon-cmd.]) +ARG_ENABL_SET([leak-detective], [enable malloc hooks to find memory leaks.]) +ARG_ENABL_SET([lock-profiler], [enable lock/mutex profiling code.]) +ARG_ENABL_SET([monolithic], [build monolithic version of libstrongswan that includes all enabled plugins. Similarly, the plugins of charon are assembled in libcharon.]) # =================================== # option to disable default options @@ -275,7 +288,20 @@ ARG_DISBL_SET([defaults], [disable all default plugins (they can be enable if test x$defaults = xfalse; then for option in $enabled_by_default; do eval test x\${${option}_given} = xtrue && continue - let $option=false + eval $option=false + done +fi + +# ============================== +# option to enable all options +# ============================== + +ARG_ENABL_SET([all], [enable all plugins and features (they can be disabled with their respective --disable options). Mainly for testing.]) + +if test x$all_given = xtrue; then + for option in $disabled_by_default; do + eval test x\${${option}_given} = xtrue && continue + eval $option=true done fi @@ -659,28 +685,43 @@ AC_RUN_IFELSE([AC_LANG_SOURCE( [AC_MSG_RESULT([no])] ) -# check for the new register_printf_specifier function with len argument, -# or the deprecated register_printf_function without -AC_CHECK_FUNC( - [register_printf_specifier], - [AC_DEFINE([HAVE_PRINTF_SPECIFIER], [], [have register_printf_specifier()])], - [AC_CHECK_FUNC( - [register_printf_function], - [AC_DEFINE([HAVE_PRINTF_FUNCTION], [], [have register_printf_function()])], - [ - AC_MSG_NOTICE([printf does not support custom format specifiers!]) - builtin_printf=true - ] - )] -) +case "$printf_hooks" in +auto|builtin|glibc|vstr) + ;; +*) + AC_MSG_NOTICE([invalid printf hook implementation, defaulting to 'auto']) + printf_hooks=auto + ;; +esac -if test x$vstr = xtrue; then - AC_CHECK_LIB([vstr],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([Vstr string library not found])],[]) - AC_DEFINE([USE_VSTR], [], [use Vstr string library for printf hooks]) - builtin_printf=false +if test x$printf_hooks = xauto -o x$printf_hooks = xglibc; then + # check for the new register_printf_specifier function with len argument, + # or the deprecated register_printf_function without + AC_CHECK_FUNC( + [register_printf_specifier], + [AC_DEFINE([HAVE_PRINTF_SPECIFIER], [], [have register_printf_specifier()])], + [AC_CHECK_FUNC( + [register_printf_function], + [AC_DEFINE([HAVE_PRINTF_FUNCTION], [], [have register_printf_function()])], + [ + AC_MSG_NOTICE([printf(3) does not support custom format specifiers!]) + if test x$printf_hooks = xglibc; then + AC_MSG_ERROR([please select a different printf hook implementation]) + else + # fallback to builtin printf hook implementation + printf_hooks=builtin + fi + ] + )] + ) fi -if test x$builtin_printf = xtrue; then +if test x$printf_hooks = xvstr; then + AC_CHECK_LIB([vstr],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([Vstr string library not found])],[]) + AC_DEFINE([USE_VSTR], [], [use Vstr string library for printf hooks]) +fi + +if test x$printf_hooks = xbuiltin; then AC_DEFINE([USE_BUILTIN_PRINTF], [], [using builtin printf for printf hooks]) fi @@ -1328,8 +1369,8 @@ AM_CONDITIONAL(USE_LIBPTTLS, test x$tnc_tnccs = xtrue) AM_CONDITIONAL(USE_FILE_CONFIG, test x$stroke = xtrue) AM_CONDITIONAL(USE_IPSEC_SCRIPT, test x$stroke = xtrue -o x$tools = xtrue -o x$conftest = xtrue) AM_CONDITIONAL(USE_LIBCAP, test x$capabilities = xlibcap) -AM_CONDITIONAL(USE_VSTR, test x$vstr = xtrue) -AM_CONDITIONAL(USE_BUILTIN_PRINTF, test x$builtin_printf = xtrue) +AM_CONDITIONAL(USE_VSTR, test x$printf_hooks = xvstr) +AM_CONDITIONAL(USE_BUILTIN_PRINTF, test x$printf_hooks = xbuiltin) AM_CONDITIONAL(USE_SIMAKA, test x$simaka = xtrue) AM_CONDITIONAL(USE_TLS, test x$tls = xtrue) AM_CONDITIONAL(USE_RADIUS, test x$radius = xtrue) diff --git a/m4/macros/enable-disable.m4 b/m4/macros/enable-disable.m4 index 2e4552068..9d51cb9b2 100644 --- a/m4/macros/enable-disable.m4 +++ b/m4/macros/enable-disable.m4 @@ -2,6 +2,7 @@ # ARG_ENABL_SET(option, help) # --------------------------- # Create a --enable-$1 option with helptext, set a variable $1 to true/false +# All $1 are collected in the variable $disabled_by_default AC_DEFUN([ARG_ENABL_SET], [AC_ARG_ENABLE( [$1], @@ -14,7 +15,8 @@ AC_DEFUN([ARG_ENABL_SET], fi], [patsubst([$1], [-], [_])=false patsubst([$1], [-], [_])_given=false] - )] + ) + disabled_by_default=${disabled_by_default}" patsubst([$1], [-], [_])"] ) # ARG_DISBL_SET(option, help) diff --git a/scripts/test.sh b/scripts/test.sh new file mode 100755 index 000000000..4785d0603 --- /dev/null +++ b/scripts/test.sh @@ -0,0 +1,65 @@ +#!/bin/sh +# Build script for Travis CI + +if test -z $TRAVIS_BUILD_DIR; then + TRAVIS_BUILD_DIR=$PWD +fi + +cd $TRAVIS_BUILD_DIR + +TARGET=check + +DEPS="libgmp-dev" + +case "$TEST" in +default) + # should be the default, but lets make sure + CONFIG="--with-printf-hooks=glibc" + ;; +openssl) + CONFIG="--disable-defaults --enable-tools --enable-openssl" + DEPS="libssl-dev" + ;; +gcrypt) + CONFIG="--disable-defaults --enable-tools --enable-gcrypt --enable-pkcs1" + DEPS="libgcrypt11-dev" + ;; +printf-builtin) + CONFIG="--with-printf-hooks=builtin" + ;; +all) + CONFIG="--enable-all --disable-android-dns --disable-android-log + --disable-dumm --disable-kernel-pfroute --disable-keychain + --disable-lock-profiler --disable-maemo --disable-padlock + --disable-osx-attr --disable-tkm --disable-uci" + # not enabled on the build server + CONFIG="$CONFIG --disable-af-alg" + # TODO: enable? perhaps via coveralls.io (cpp-coveralls)? + CONFIG="$CONFIG --disable-coverage" + DEPS="$DEPS libcurl4-gnutls-dev libsoup2.4-dev libunbound-dev libldns-dev + libmysqlclient-dev libsqlite3-dev clearsilver-dev libfcgi-dev + libnm-glib-dev libnm-glib-vpn-dev libpcsclite-dev libpam0g-dev + binutils-dev libunwind7-dev" + ;; +dist) + TARGET=distcheck + ;; +*) + echo "$0: unknown test $TEST" >&2 + exit 1 + ;; +esac + +if test "$1" = "deps"; then + sudo apt-get install -qq $DEPS + exit $? +fi + +CONFIG="$CONFIG + --enable-silent-rules + --enable-test-vectors + --enable-monolithic=${MONOLITHIC-no} + --enable-leak-detective=${LEAK_DETECTIVE-no}" + +echo "$ ./configure $CONFIG && make $TARGET" +./configure $CONFIG && make -j4 $TARGET diff --git a/src/libcharon/plugins/tnc_pdp/Makefile.am b/src/libcharon/plugins/tnc_pdp/Makefile.am index cc7c934d8..48de82571 100644 --- a/src/libcharon/plugins/tnc_pdp/Makefile.am +++ b/src/libcharon/plugins/tnc_pdp/Makefile.am @@ -15,12 +15,13 @@ if MONOLITHIC noinst_LTLIBRARIES = libstrongswan-tnc-pdp.la else plugin_LTLIBRARIES = libstrongswan-tnc-pdp.la +endif + libstrongswan_tnc_pdp_la_LIBADD = \ $(top_builddir)/src/libradius/libradius.la \ $(top_builddir)/src/libpttls/libpttls.la \ $(top_builddir)/src/libtls/libtls.la \ $(top_builddir)/src/libtnccs/libtnccs.la -endif libstrongswan_tnc_pdp_la_SOURCES = \ tnc_pdp_plugin.h tnc_pdp_plugin.c \ diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c index dba3f6f6d..69225bd1e 100644 --- a/src/libstrongswan/crypto/crypto_factory.c +++ b/src/libstrongswan/crypto/crypto_factory.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2013-2014 Tobias Brunner * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -20,6 +20,7 @@ #include #include #include +#include const char *default_plugin_name = "default"; @@ -976,3 +977,39 @@ crypto_factory_t *crypto_factory_create() return &this->public; } + +/** + * Manually verify all registered algorithms against test vectors + */ +static u_int verify_registered_algorithms(crypto_factory_t *factory) +{ + private_crypto_factory_t *this = (private_crypto_factory_t*)factory; + enumerator_t *enumerator; + entry_t *entry; + u_int failures = 0; + +#define TEST_ALGORITHMS(test, ...) do { \ + enumerator = this->test##s->create_enumerator(this->test##s); \ + while (enumerator->enumerate(enumerator, &entry)) \ + { \ + if (!this->tester->test_##test(this->tester, entry->algo, ##__VA_ARGS__, \ + entry->create_##test, NULL, entry->plugin_name)) \ + { \ + failures++; \ + } \ + } \ + enumerator->destroy(enumerator); \ +} while (0) + + this->lock->read_lock(this->lock); + TEST_ALGORITHMS(crypter, 0); + TEST_ALGORITHMS(aead, 0); + TEST_ALGORITHMS(signer); + TEST_ALGORITHMS(hasher); + TEST_ALGORITHMS(prf); + TEST_ALGORITHMS(rng); + this->lock->unlock(this->lock); + return failures; +} + +EXPORT_FUNCTION_FOR_TESTS(crypto, verify_registered_algorithms); diff --git a/src/libstrongswan/crypto/crypto_tester.c b/src/libstrongswan/crypto/crypto_tester.c index 30724b16d..40c4fd362 100644 --- a/src/libstrongswan/crypto/crypto_tester.c +++ b/src/libstrongswan/crypto/crypto_tester.c @@ -204,16 +204,13 @@ METHOD(crypto_tester_t, test_crypter, bool, continue; } - tested++; - failed = TRUE; crypter = create(alg, vector->key_size); if (!crypter) - { - DBG1(DBG_LIB, "%N[%s]: %u bit key size not supported", - encryption_algorithm_names, alg, plugin_name, - BITS_PER_BYTE * vector->key_size); + { /* key size not supported */ continue; } + tested++; + failed = TRUE; key = chunk_create(vector->key, crypter->get_key_size(crypter)); if (!crypter->set_key(crypter, key)) diff --git a/src/libstrongswan/tests/suites/test_ntru.c b/src/libstrongswan/tests/suites/test_ntru.c index 3204c89a8..9e6c5d74d 100644 --- a/src/libstrongswan/tests/suites/test_ntru.c +++ b/src/libstrongswan/tests/suites/test_ntru.c @@ -94,7 +94,8 @@ START_TEST(test_ntru_drbg_strength) entropy = lib->crypto->create_rng(lib->crypto, RNG_STRONG); ck_assert(entropy != NULL); - drbg = ntru_drbg_create(strengths[_i].requested, chunk_empty, entropy); + drbg = TEST_FUNCTION(ntru, ntru_drbg_create, strengths[_i].requested, + chunk_empty, entropy); if (strengths[_i].standard) { ck_assert(drbg != NULL); @@ -251,7 +252,8 @@ START_TEST(test_ntru_drbg) out = chunk_alloc(128); entropy = test_rng_create(drbg_tests[_i].entropy); - drbg = ntru_drbg_create(256, drbg_tests[_i].pers_str, entropy); + drbg = TEST_FUNCTION(ntru, ntru_drbg_create, 256, drbg_tests[_i].pers_str, + entropy); ck_assert(drbg != NULL); ck_assert(drbg->reseed(drbg)); ck_assert(drbg->generate(drbg, 256, 128, out.ptr)); @@ -273,7 +275,7 @@ START_TEST(test_ntru_drbg_reseed) "libstrongswan.plugins.ntru.max_drbg_requests", 2); out = chunk_alloc(128); entropy = test_rng_create(drbg_tests[0].entropy); - drbg = ntru_drbg_create(256, chunk_empty, entropy); + drbg = TEST_FUNCTION(ntru, ntru_drbg_create, 256, chunk_empty, entropy); /* bad output parameters */ ck_assert(!drbg->generate(drbg, 256, 0, out.ptr)); @@ -291,13 +293,13 @@ START_TEST(test_ntru_drbg_reseed) drbg->destroy(drbg); /* no entropy available for DRBG instantiation */ - drbg = ntru_drbg_create(256, chunk_empty, entropy); + drbg = TEST_FUNCTION(ntru, ntru_drbg_create, 256, chunk_empty, entropy); ck_assert(drbg == NULL); entropy->destroy(entropy); /* one automatic reseeding occurs */ entropy = test_rng_create(drbg_tests[0].entropy); - drbg = ntru_drbg_create(256, chunk_empty, entropy); + drbg = TEST_FUNCTION(ntru, ntru_drbg_create, 256, chunk_empty, entropy); ck_assert(drbg->generate(drbg, 256, 128, out.ptr)); ck_assert(drbg->generate(drbg, 256, 128, out.ptr)); ck_assert(drbg->generate(drbg, 256, 128, out.ptr)); @@ -382,7 +384,7 @@ uint16_t indices_ees1171ep1[] = { */ mgf1_test_t mgf1_tests[] = { { HASH_SHA1, 20, 60, 20, 15, 24, - chunk_from_chars( + chunk_from_chars( 0xED, 0xA5, 0xC3, 0xBC, 0xAF, 0xB3, 0x20, 0x7D, 0x14, 0xA1, 0x54, 0xF7, 0x8B, 0x37, 0xF2, 0x8D, 0x8C, 0x9B, 0xD5, 0x63, 0x57, 0x38, 0x11, 0xC2, @@ -416,7 +418,7 @@ mgf1_test_t mgf1_tests[] = { 0x40, 0x4B, 0xE7, 0x22, 0x3A, 0x56, 0x10, 0x6D, 0x4D, 0x29, 0x0B, 0xCE, 0xA6, 0x21, 0xB5, 0x5C, 0x71, 0x66, 0x2F, 0x70, 0x35, 0xD8, 0x8A, 0x92, - 0x33, 0xF0, 0x16, 0xD4, 0x0E, 0x43, 0x8A, 0x14), + 0x33, 0xF0, 0x16, 0xD4, 0x0E, 0x43, 0x8A, 0x14), chunk_from_chars( 1, 2, 1, 0, 0, 1, 1, 1, 2, 0, 1, 0, 1, 1, 1, 0, 2, 0, 1, 1, 0, 0, 0, 1, 1, 0, 2, 0, 2, 2, 1, 2, 2, 2, 1, 2, 1, 1, 0, 0, @@ -474,7 +476,7 @@ mgf1_test_t mgf1_tests[] = { 0x76, 0x89, 0x8B, 0x1B, 0x60, 0xEC, 0x10, 0x9D, 0x8F, 0x13, 0xF2, 0xFE, 0xD9, 0x85, 0xC1, 0xAB, 0x7E, 0xEE, 0xB1, 0x31, 0xDD, 0xF7, 0x7F, 0x0C, - 0x7D, 0xF9, 0x6B, 0x7B, 0x19, 0x80, 0xBD, 0x28), + 0x7D, 0xF9, 0x6B, 0x7B, 0x19, 0x80, 0xBD, 0x28), chunk_from_chars( 0xF1, 0x19, 0x02, 0x4F, 0xDA, 0x58, 0x05, 0x9A, 0x07, 0xDF, 0x61, 0x81, 0x22, 0x0E, 0x15, 0x46, @@ -550,14 +552,17 @@ START_TEST(test_ntru_mgf1) mask2.len = mgf1_tests[_i].ml2; mask3.len = mgf1_tests[_i].ml3; - mgf1 = ntru_mgf1_create(HASH_UNKNOWN, mgf1_tests[_i].seed, TRUE); + mgf1 = TEST_FUNCTION(ntru, ntru_mgf1_create, HASH_UNKNOWN, + mgf1_tests[_i].seed, TRUE); ck_assert(mgf1 == NULL); - mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, chunk_empty, TRUE); + mgf1 = TEST_FUNCTION(ntru, ntru_mgf1_create, mgf1_tests[_i].alg, + chunk_empty, TRUE); ck_assert(mgf1 == NULL); /* return mask in allocated chunk */ - mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].seed, TRUE); + mgf1 = TEST_FUNCTION(ntru, ntru_mgf1_create, mgf1_tests[_i].alg, + mgf1_tests[_i].seed, TRUE); ck_assert(mgf1); /* check hash size */ @@ -573,14 +578,16 @@ START_TEST(test_ntru_mgf1) mgf1->destroy(mgf1); /* copy mask to pre-allocated buffer */ - mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].seed, TRUE); + mgf1 = TEST_FUNCTION(ntru, ntru_mgf1_create, mgf1_tests[_i].alg, + mgf1_tests[_i].seed, TRUE); ck_assert(mgf1); ck_assert(mgf1->get_mask(mgf1, mgf1_tests[_i].mask.len, mask.ptr)); ck_assert(chunk_equals(mask, mgf1_tests[_i].mask)); mgf1->destroy(mgf1); /* get mask in batches without hashing the seed */ - mgf1 = ntru_mgf1_create(mgf1_tests[_i].alg, mgf1_tests[_i].hashed_seed, FALSE); + mgf1 = TEST_FUNCTION(ntru, ntru_mgf1_create, mgf1_tests[_i].alg, + mgf1_tests[_i].hashed_seed, FALSE); ck_assert(mgf1); /* first batch */ @@ -608,16 +615,16 @@ START_TEST(test_ntru_trits) ntru_trits_t *mask; chunk_t trits; - mask = ntru_trits_create(mgf1_tests[_i].trits.len, HASH_UNKNOWN, - mgf1_tests[_i].seed); + mask = TEST_FUNCTION(ntru, ntru_trits_create, mgf1_tests[_i].trits.len, + HASH_UNKNOWN, mgf1_tests[_i].seed); ck_assert(mask == NULL); - mask = ntru_trits_create(mgf1_tests[_i].trits.len, mgf1_tests[_i].alg, - chunk_empty); + mask = TEST_FUNCTION(ntru, ntru_trits_create, mgf1_tests[_i].trits.len, + mgf1_tests[_i].alg, chunk_empty); ck_assert(mask == NULL); - mask = ntru_trits_create(mgf1_tests[_i].trits.len, mgf1_tests[_i].alg, - mgf1_tests[_i].seed); + mask = TEST_FUNCTION(ntru, ntru_trits_create, mgf1_tests[_i].trits.len, + mgf1_tests[_i].alg, mgf1_tests[_i].seed); ck_assert(mask); trits = chunk_create(mask->get_trits(mask), mask->get_size(mask)); @@ -625,7 +632,8 @@ START_TEST(test_ntru_trits) mask->destroy(mask); /* generate a multiple of 5 trits */ - mask = ntru_trits_create(10, mgf1_tests[_i].alg, mgf1_tests[_i].seed); + mask = TEST_FUNCTION(ntru, ntru_trits_create, 10, mgf1_tests[_i].alg, + mgf1_tests[_i].seed); ck_assert(mask); trits = chunk_create(mask->get_trits(mask), mask->get_size(mask)); @@ -646,17 +654,17 @@ START_TEST(test_ntru_poly) seed.len = mgf1_tests[_i].seed_len; p = &mgf1_tests[_i].poly_test[0]; - poly = ntru_poly_create_from_seed(HASH_UNKNOWN, seed, p->c_bits, p->N, p->q, - p->indices_len, p->indices_len, - p->is_product_form); + poly = TEST_FUNCTION(ntru, ntru_poly_create_from_seed, HASH_UNKNOWN, seed, + p->c_bits, p->N, p->q, p->indices_len, p->indices_len, + p->is_product_form); ck_assert(poly == NULL); for (n = 0; n < 2; n++) { p = &mgf1_tests[_i].poly_test[n]; - poly = ntru_poly_create_from_seed(mgf1_tests[_i].alg, seed, p->c_bits, - p->N, p->q, p->indices_len, - p->indices_len, p->is_product_form); + poly = TEST_FUNCTION(ntru, ntru_poly_create_from_seed, + mgf1_tests[_i].alg, seed, p->c_bits, p->N, p->q, + p->indices_len, p->indices_len, p->is_product_form); ck_assert(poly != NULL && poly->get_size(poly) == p->indices_size); indices = poly->get_indices(poly); @@ -756,8 +764,9 @@ START_TEST(test_ntru_ring_mult) int i; t = &ring_mult_tests[_i]; - poly = ntru_poly_create_from_data(t->indices, t->N, t->q, t->indices_len_p, - t->indices_len_m, t->is_product_form); + poly = TEST_FUNCTION(ntru, ntru_poly_create_from_data, t->indices, t->N, + t->q, t->indices_len_p, t->indices_len_m, + t->is_product_form); ck_assert(poly != NULL); c = malloc(t->N * sizeof(uint16_t)); @@ -784,8 +793,9 @@ START_TEST(test_ntru_array) t = &ring_mult_tests[array_tests[_i]]; - poly = ntru_poly_create_from_data(t->indices, t->N, t->q, t->indices_len_p, - t->indices_len_m, t->is_product_form); + poly = TEST_FUNCTION(ntru, ntru_poly_create_from_data, t->indices, t->N, + t->q, t->indices_len_p, t->indices_len_m, + t->is_product_form); ck_assert(poly != NULL); c = malloc(t->N * sizeof(uint16_t)); @@ -803,8 +813,8 @@ END_TEST START_TEST(test_ntru_param_set) { - ck_assert(ntru_param_set_get_by_id(-1) == NULL); - ck_assert(ntru_param_set_get_by_id(16) == NULL); + ck_assert(TEST_FUNCTION(ntru, ntru_param_set_get_by_id, -1) == NULL); + ck_assert(TEST_FUNCTION(ntru, ntru_param_set_get_by_id, 16) == NULL); } END_TEST @@ -964,7 +974,7 @@ privkey_test_t privkey_tests[] = { 0xB1, 0x6D, 0x88, 0x41, 0x62, 0x4D, 0x18, 0xB6, 0x3F, 0x12, 0x81, 0xDE, 0xE6, 0xDC, 0x4A, 0x31, 0x61, 0x26, 0xB1, 0x4B, 0x95, 0xC1, 0x69, 0xDC, - 0xDC, 0xAC, 0xD0, 0x15, 0xFC, 0x21, 0xC5, 0x20, + 0xDC, 0xAC, 0xD0, 0x15, 0xFC, 0x21, 0xC5, 0x20, 0x5F, 0x97, 0x76, 0x41, 0xC1, 0xF2, 0xD7, 0x95, 0x1D, 0x25, 0x23, 0x36, 0x86, 0xFA, 0x7E, 0xF4, 0x14, 0x9F, 0x9D, 0x9F, 0xB2, 0xBB, 0x25, 0x1D, @@ -1066,13 +1076,15 @@ START_TEST(test_ntru_privkey) uint32_t strength; chunk_t encoding, privkey_encoding, pubkey_encoding; - params = ntru_param_set_get_by_id(privkey_tests[_i].id); + params = TEST_FUNCTION(ntru, ntru_param_set_get_by_id, + privkey_tests[_i].id); strength = params->sec_strength_len * BITS_PER_BYTE; entropy = test_rng_create(privkey_tests[_i].entropy); - drbg = ntru_drbg_create(strength, chunk_from_str("IKE NTRU-KE"), entropy); + drbg = TEST_FUNCTION(ntru, ntru_drbg_create, strength, + chunk_from_str("IKE NTRU-KE"), entropy); ck_assert(drbg != NULL); - privkey = ntru_private_key_create(drbg, params); + privkey = TEST_FUNCTION(ntru, ntru_private_key_create, drbg, params); ck_assert(privkey); privkey_encoding = privkey->get_encoding(privkey); diff --git a/src/libstrongswan/tests/suites/test_vectors.c b/src/libstrongswan/tests/suites/test_vectors.c index 242ac9d09..a1205d0be 100644 --- a/src/libstrongswan/tests/suites/test_vectors.c +++ b/src/libstrongswan/tests/suites/test_vectors.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2014 Tobias Brunner + * Hochschule fuer Technik Rapperswil + * * Copyright (C) 2013 Martin Willi * Copyright (C) 2013 revosec AG * @@ -15,13 +18,15 @@ #include "test_suite.h" -/******************************************************************************* - * Check if test vectors have been successful during transform registration - */ +#include + +IMPORT_FUNCTION_FOR_TESTS(crypto, verify_registered_algorithms, u_int, + crypto_factory_t *factory); START_TEST(test_vectors) { - u_int failed = lib->crypto->get_test_vector_failures(lib->crypto); + u_int failed = TEST_FUNCTION(crypto, verify_registered_algorithms, + lib->crypto); fail_if(failed > 0, "%u test vectors failed", failed); } END_TEST diff --git a/src/libstrongswan/tests/test_runner.c b/src/libstrongswan/tests/test_runner.c index 0b26ee128..6bb1b290c 100644 --- a/src/libstrongswan/tests/test_runner.c +++ b/src/libstrongswan/tests/test_runner.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -32,31 +33,85 @@ #define TTY(color) tty_escape_get(2, TTY_FG_##color) /** - * Initialize the lookup table for testable functions (defined in libstrongswan) + * Initialize the lookup table for testable functions (defined in + * libstrongswan). We don't use the constructor attribute as the order can't + * really be defined (clang does not support it and gcc does not adhere to it in + * the monolithic build). The function here is a weak symbol in libstrongswan. */ -static void testable_functions_create() __attribute__ ((constructor(1000))); -static void testable_functions_create() +void testable_functions_create() { - testable_functions = hashtable_create(hashtable_hash_str, - hashtable_equals_str, 8); + if (!testable_functions) + { + testable_functions = hashtable_create(hashtable_hash_str, + hashtable_equals_str, 8); + } } /** * Destroy the lookup table for testable functions */ -static void testable_functions_destroy() __attribute__ ((destructor(1000))); +static void testable_functions_destroy() __attribute__ ((destructor)); static void testable_functions_destroy() { - testable_functions->destroy(testable_functions); + DESTROY_IF(testable_functions); /* if leak detective is enabled plugins are not actually unloaded, which * means their destructor is called AFTER this one when the process - * terminates, even though the priority says differently, make sure this - * does not crash */ + * terminates, make sure this does not crash */ testable_functions = NULL; } /** - * Load all available test suites + * Destroy a single test suite and associated data + */ +static void destroy_suite(test_suite_t *suite) +{ + test_case_t *tcase; + + while (array_remove(suite->tcases, 0, &tcase)) + { + array_destroy(tcase->functions); + array_destroy(tcase->fixtures); + } + free(suite); +} + +/** + * Removes and destroys test suites that are not selected. + */ +static void filter_suites(array_t *loaded) +{ + enumerator_t *enumerator, *names; + hashtable_t *selected; + test_suite_t *suite; + char *suites, *name; + + suites = getenv("TESTS_SUITES"); + if (!suites) + { + return; + } + selected = hashtable_create(hashtable_hash_str, hashtable_equals_str, 8); + names = enumerator_create_token(suites, ",", " "); + while (names->enumerate(names, &name)) + { + selected->put(selected, name, name); + } + enumerator = array_create_enumerator(loaded); + while (enumerator->enumerate(enumerator, &suite)) + { + if (!selected->get(selected, suite->name)) + { + array_remove_at(loaded, enumerator); + destroy_suite(suite); + } + } + enumerator->destroy(enumerator); + selected->destroy(selected); + names->destroy(names); +} + +/** + * Load all available test suites, or optionally only selected ones. */ static array_t *load_suites(test_configuration_t configs[], test_runner_init_t init) @@ -91,6 +146,7 @@ static array_t *load_suites(test_configuration_t configs[], array_insert(suites, -1, configs[i].suite()); } } + filter_suites(suites); if (lib->leak_detective) { @@ -112,16 +168,10 @@ static array_t *load_suites(test_configuration_t configs[], static void unload_suites(array_t *suites) { test_suite_t *suite; - test_case_t *tcase; while (array_remove(suites, 0, &suite)) { - while (array_remove(suite->tcases, 0, &tcase)) - { - array_destroy(tcase->functions); - array_destroy(tcase->fixtures); - } - free(suite); + destroy_suite(suite); } array_destroy(suites); } @@ -178,6 +228,9 @@ static bool call_fixture(test_case_t *tcase, bool up) */ static bool pre_test(test_runner_init_t init) { + level_t level = LEVEL_SILENT; + char *verbosity; + library_init(NULL, "test-runner"); /* use non-blocking RNG to generate keys fast */ @@ -185,6 +238,9 @@ static bool pre_test(test_runner_init_t init) "libstrongswan.plugins.random.random", lib->settings->get_str(lib->settings, "libstrongswan.plugins.random.urandom", "/dev/urandom")); + /* same for the gcrypt plugin */ + lib->settings->set_default_str(lib->settings, + "libstrongswan.plugins.gcrypt.quick_random", "yes"); if (lib->leak_detective) { @@ -197,7 +253,12 @@ static bool pre_test(test_runner_init_t init) library_deinit(); return FALSE; } - dbg_default_set_level(LEVEL_SILENT); + verbosity = getenv("TESTS_VERBOSITY"); + if (verbosity) + { + level = atoi(verbosity); + } + dbg_default_set_level(level); return TRUE; } diff --git a/src/libstrongswan/utils/test.c b/src/libstrongswan/utils/test.c index 7de5a7661..624ac4b34 100644 --- a/src/libstrongswan/utils/test.c +++ b/src/libstrongswan/utils/test.c @@ -22,29 +22,46 @@ */ hashtable_t *testable_functions; +/** + * The function that actually initializes the hash table above. Provided + * by the test runner. + */ +void testable_functions_create() __attribute__((weak)); + /* * Described in header. */ void testable_function_register(char *name, void *fn) { - if (testable_functions) + bool old = FALSE; + + if (!testable_functions_create) + { /* not linked to the test runner */ + return; + } + else if (!fn && !testable_functions) + { /* ignore as testable_functions has already been destroyed */ + return; + } + + if (lib && lib->leak_detective) { - bool old = FALSE; - if (lib->leak_detective) - { - old = lib->leak_detective->set_state(lib->leak_detective, FALSE); - } - if (fn) - { - testable_functions->put(testable_functions, name, fn); - } - else - { - testable_functions->remove(testable_functions, name); - } - if (lib->leak_detective) - { - lib->leak_detective->set_state(lib->leak_detective, old); - } + old = lib->leak_detective->set_state(lib->leak_detective, FALSE); + } + if (!testable_functions) + { + testable_functions_create(); + } + if (fn) + { + testable_functions->put(testable_functions, name, fn); + } + else + { + testable_functions->remove(testable_functions, name); + } + if (lib && lib->leak_detective) + { + lib->leak_detective->set_state(lib->leak_detective, old); } } diff --git a/src/libstrongswan/utils/test.h b/src/libstrongswan/utils/test.h index 5b7289244..51362a15b 100644 --- a/src/libstrongswan/utils/test.h +++ b/src/libstrongswan/utils/test.h @@ -51,7 +51,7 @@ void testable_function_register(char *name, void *fn); * @param fn function to register */ #define EXPORT_FUNCTION_FOR_TESTS(ns, fn) \ -static void testable_function_register_##fn() __attribute__ ((constructor(2000))); \ +static void testable_function_register_##fn() __attribute__ ((constructor)); \ static void testable_function_register_##fn() \ { \ testable_function_register(#ns "/" #fn, fn); \ @@ -65,32 +65,32 @@ static void testable_function_unregister_##fn() \ /** * Import a registered function so that it can be called from tests. * - * @note If the imported function is static (or no conflicting header files - * are included) ret can be prefixed with static to declare the function static. - * - * @note We allocate an arbitrary amount of stack space, hopefully enough for - * all arguments. - * * @param ns namespace of the function * @param name name of the function * @param ret return type of the function * @param ... arguments of the function */ #define IMPORT_FUNCTION_FOR_TESTS(ns, name, ret, ...) \ -ret name(__VA_ARGS__) \ -{ \ - void (*fn)() = NULL; \ - if (testable_functions) \ +static ret (*TEST_##ns##name)(__VA_ARGS__); + +/** + * Call a registered function from tests. + * + * @param ns namespace of the function + * @param name name of the function + * @param ... arguments for the function + */ +#define TEST_FUNCTION(ns, name, ...) \ +({ \ + if (!TEST_##ns##name && testable_functions) \ { \ - fn = testable_functions->get(testable_functions, #ns "/" #name); \ + TEST_##ns##name = testable_functions->get(testable_functions, #ns "/" #name); \ } \ - if (fn) \ + if (!TEST_##ns##name) \ { \ - void *args = __builtin_apply_args(); \ - __builtin_return(__builtin_apply(fn, args, 16*sizeof(void*))); \ + test_fail_msg(__FILE__, __LINE__, "function " #name " (" #ns ") not found"); \ } \ - test_fail_msg(__FILE__, __LINE__, "function " #name " (" #ns ") not found"); \ - __builtin_return(NULL); \ -} + TEST_##ns##name(__VA_ARGS__); \ +}) #endif /** TEST_H_ @}*/