diff options
-rw-r--r-- | .gitlab-ci.yml | 8 | ||||
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | lib/libgnutls.map | 1 | ||||
-rw-r--r-- | lib/pkcs11.c | 41 | ||||
-rw-r--r-- | tests/Makefile.am | 11 | ||||
-rwxr-xr-x | tests/destructive/p11-kit-load.sh | 144 | ||||
-rw-r--r-- | tests/pkcs11/list-tokens.c | 117 |
7 files changed, 320 insertions, 10 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8e7467cbb4..74748f48b6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -158,9 +158,9 @@ asan/Fedora/x86_64: - make -j$(nproc) - LSAN_OPTIONS="suppressions=$(pwd)/fuzz/lsan.supp" make check -j$(nproc) - CFLAGS="-fsanitize=address -g -O2" LDFLAGS="-static-libasan" - ./configure --disable-doc --with-default-trust-store-pkcs11="pkcs11:" --disable-guile + ./configure --disable-doc --with-default-trust-store-pkcs11="pkcs11:" --disable-guile --enable-destructive-tests - make -j$(nproc) - - make -C tests check -j$(nproc) TESTS=trust-store SUBDIRS=. + - make -C tests check -j$(nproc) TESTS="trust-store destructive/p11-kit-load.sh" SUBDIRS=. tags: - shared except: @@ -383,9 +383,9 @@ ubsan-Werror/Fedora/x86_64: - make -j$(nproc) -C src CFLAGS="-Werror -O2 -g -fsanitize=undefined -Wno-error=parentheses -Wno-error=unused-macros" - make -j$(nproc) - make check -j$(nproc) - - CFLAGS="-fsanitize=undefined -fsanitize=bool -fsanitize=alignment -fsanitize=null -fsanitize=bounds-strict -fsanitize=enum -fno-sanitize-recover -g -O2" LDFLAGS="-static-libubsan" ./configure --disable-non-suiteb-curves --disable-guile --disable-doc --with-default-trust-store-pkcs11="pkcs11:" + - CFLAGS="-fsanitize=undefined -fsanitize=bool -fsanitize=alignment -fsanitize=null -fsanitize=bounds-strict -fsanitize=enum -fno-sanitize-recover -g -O2" LDFLAGS="-static-libubsan" ./configure --disable-non-suiteb-curves --disable-guile --disable-doc --with-default-trust-store-pkcs11="pkcs11:" --enable-destructive-tests - make -j$(nproc) - - make -C tests check -j$(nproc) TESTS=trust-store SUBDIRS=. + - make -C tests check -j$(nproc) TESTS="trust-store destructive/p11-kit-load.sh" SUBDIRS=. tags: - shared except: diff --git a/configure.ac b/configure.ac index b5e6cafdfa..6b46887509 100644 --- a/configure.ac +++ b/configure.ac @@ -254,6 +254,11 @@ AC_ARG_ENABLE(tests, enable_tests=$enableval, enable_tests=$enable_tools) AM_CONDITIONAL(ENABLE_TESTS, test "$enable_tests" != "no") +AC_ARG_ENABLE(destructive-tests, + AS_HELP_STRING([--enable-destructive-tests], [compile and run tests which touch outside gnutls' code boundary]), + enable_destructive_tests=$enableval, enable_destructive_tests=no) +AM_CONDITIONAL(ENABLE_DESTRUCTIVE_TESTS, test "$enable_destructive_tests" != "no") + AC_ARG_ENABLE(fuzzer-target, AS_HELP_STRING([--enable-fuzzer-target], [make a library intended for testing - not production]), enable_fuzzer_target=$enableval, enable_fuzzer_target=no) @@ -729,6 +734,8 @@ if test "x$with_default_trust_store_pkcs11" != x; then ["$with_default_trust_store_pkcs11"], [use the given pkcs11 uri as default trust store]) fi +AM_CONDITIONAL([HAVE_PKCS11_TRUST_STORE], [test -n "${with_default_trust_store_pkcs11}"]) + AC_ARG_WITH([default-trust-store-dir], [AS_HELP_STRING([--with-default-trust-store-dir=DIR], [use the given directory as default trust store])]) @@ -981,6 +988,7 @@ AC_MSG_NOTICE([summary of build options: Local unistring: ${included_unistring} Use nettle-mini: ${mini_nettle} Documentation: ${enable_doc} (manpages: ${enable_manpages}) + Destructive tests: ${enable_destructive_tests} ]) AC_MSG_NOTICE([External hardware support: diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 43a6b13212..16c582c6f6 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1241,6 +1241,7 @@ GNUTLS_PRIVATE_3_4 { _gnutls_mpi_log; _gnutls_mpi_release; # Internal symbols needed by tests/: + _gnutls_pkcs11_token_get_url; _gnutls_pkcs12_string_to_key; _gnutls_bin2hex; _gnutls_mac_to_entry; diff --git a/lib/pkcs11.c b/lib/pkcs11.c index ceb05bbe8d..5955f19c61 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -2192,11 +2192,18 @@ find_token_modname_cb(struct ck_function_list *module, struct pkcs11_session_inf return 0; } +/* Internal symbol used by tests */ +int +_gnutls_pkcs11_token_get_url(unsigned int seq, + gnutls_pkcs11_url_type_t detailed, char **url, + unsigned flags); + /** - * gnutls_pkcs11_token_get_url: + * _gnutls_pkcs11_token_get_url: * @seq: sequence number starting from 0 * @detailed: non zero if a detailed URL is required * @url: will contain an allocated url + * @flags: zero or 1. When 1 no initialization is performed. * * This function will return the URL for each token available * in system. The url has to be released using gnutls_free() @@ -2205,16 +2212,18 @@ find_token_modname_cb(struct ck_function_list *module, struct pkcs11_session_inf * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number * exceeds the available tokens, otherwise a negative error value. * - * Since: 2.12.0 **/ int -gnutls_pkcs11_token_get_url(unsigned int seq, - gnutls_pkcs11_url_type_t detailed, char **url) +_gnutls_pkcs11_token_get_url(unsigned int seq, + gnutls_pkcs11_url_type_t detailed, char **url, + unsigned flags) { int ret; struct find_token_num tn; - PKCS11_CHECK_INIT; + if (!(flags & 1)) { + PKCS11_CHECK_INIT; + } memset(&tn, 0, sizeof(tn)); tn.seq = seq; @@ -2239,6 +2248,28 @@ gnutls_pkcs11_token_get_url(unsigned int seq, } /** + * gnutls_pkcs11_token_get_url: + * @seq: sequence number starting from 0 + * @detailed: non zero if a detailed URL is required + * @url: will contain an allocated url + * + * This function will return the URL for each token available + * in system. The url has to be released using gnutls_free() + * + * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, + * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE if the sequence number + * exceeds the available tokens, otherwise a negative error value. + * + * Since: 2.12.0 + **/ +int +gnutls_pkcs11_token_get_url(unsigned int seq, + gnutls_pkcs11_url_type_t detailed, char **url) +{ + return _gnutls_pkcs11_token_get_url(seq, detailed, url, 0); +} + +/** * gnutls_pkcs11_token_get_info: * @url: should contain a PKCS 11 URL * @ttype: Denotes the type of information requested diff --git a/tests/Makefile.am b/tests/Makefile.am index 250f42640b..18d8b3eaa4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -88,6 +88,7 @@ noinst_LTLIBRARIES = libutils.la libutils_la_SOURCES = utils.h utils.c seccomp.c utils-adv.c libutils_la_LIBADD = ../lib/libgnutls.la +indirect_tests = ctests = mini-record-2 simple gc set_pkcs12_cred cert certuniqueid tls-neg-ext-key \ mpi certificate_set_x509_crl dn parse_ca x509-dn x509-dn-decode record-sizes \ hostname-check cve-2008-4989 pkcs12_s2k chainverify record-sizes-range \ @@ -309,7 +310,6 @@ name_constraints_merge_CPPFLAGS = $(AM_CPPFLAGS) \ -I$(top_builddir)/gl \ $(NETTLE_CFLAGS) -check_PROGRAMS = $(ctests) dist_check_SCRIPTS = rfc2253-escape-test rsa-md5-collision/rsa-md5-collision.sh systemkey.sh if !WINDOWS @@ -323,12 +323,21 @@ dist_check_SCRIPTS += fastopen.sh pkgconfig.sh starttls.sh starttls-ftp.sh start if ENABLE_PKCS11 dist_check_SCRIPTS += p11-kit-trust.sh + +if ENABLE_DESTRUCTIVE_TESTS +if HAVE_PKCS11_TRUST_STORE +dist_check_SCRIPTS += destructive/p11-kit-load.sh +indirect_tests += pkcs11/list-tokens +endif +endif + endif if ENABLE_DANE dist_check_SCRIPTS += danetool.sh endif endif +check_PROGRAMS = $(ctests) $(indirect_tests) TESTS = $(ctests) $(dist_check_SCRIPTS) TESTS_ENVIRONMENT = \ diff --git a/tests/destructive/p11-kit-load.sh b/tests/destructive/p11-kit-load.sh new file mode 100755 index 0000000000..2fe6394fe2 --- /dev/null +++ b/tests/destructive/p11-kit-load.sh @@ -0,0 +1,144 @@ +#!/bin/sh + +# Copyright (C) 2017 Red Hat, Inc. +# +# This file is part of p11-kit. +# +# p11-kit is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# p11-kit is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/> + +#set -e + +srcdir="${srcdir:-.}" +builddir="${builddir:-.}" +P11TOOL="${P11TOOL:-../src/p11tool${EXEEXT}}" +CERTTOOL="${CERTTOOL:-../src/certtool${EXEEXT}}" +DIFF="${DIFF:-diff}" +PKGCONFIG="${PKG_CONFIG:-$(which pkg-config)}" + +for lib in ${libdir} ${libdir}/pkcs11 /usr/lib64/pkcs11/ /usr/lib/pkcs11/ /usr/lib/x86_64-linux-gnu/pkcs11/;do + if test -f "${lib}/p11-kit-trust.so"; then + TRUST_MODULE="${lib}/p11-kit-trust.so" + echo "located ${MODULE}" + break + fi +done + +for lib in ${libdir} ${libdir}/pkcs11 /usr/lib64/pkcs11/ /usr/lib/pkcs11/ /usr/lib/x86_64-linux-gnu/pkcs11/;do + if test -f "${lib}/libsofthsm2.so"; then + SOFTHSM_MODULE="${lib}/libsofthsm2.so" + echo "located ${MODULE}" + break + fi +done + +${PKGCONFIG} --version >/dev/null || exit 77 + +if ! test -x "${P11TOOL}"; then + echo "p11tool was not found" + exit 77 +fi + +if ! test -f "${TRUST_MODULE}"; then + echo "p11-kit trust module was not found" + exit 77 +fi + +if ! test -f "${SOFTHSM_MODULE}"; then + echo "softhsm module was not found" + exit 77 +fi + +# Create pkcs11.conf with two modules, a trusted (p11-kit-trust) +# and softhsm (not trusted) +DIR=$(${PKGCONFIG} --var=p11_system_config_modules p11-kit-1) +rm -f ${DIR}/* + +cat <<_EOF_ >${DIR}/p11-kit-trust.module +module: p11-kit-trust.so +trust-policy: yes +_EOF_ + +cat <<_EOF_ >${DIR}/softhsm.module +module: libsofthsm2.so +_EOF_ + +# Check whether p11tool would list them both + +nr=$(${P11TOOL} --list-tokens|grep -c ^Token) +if test "$nr" != 2;then + echo "Error: did not find 2 modules" + ${P11TOOL} --list-tokens +fi + +# Check whether p11tool with a specific provider would list only that + +nr=$(${P11TOOL} --provider "${SOFTHSM_MODULE}" --list-tokens|grep -c ^Token) +if test "$nr" != 1;then + echo "Error: did not find softhsm modules" + ${P11TOOL} --list-tokens --provider "${SOFTHSM_MODULE}" +fi + + +# Check whether p11tool will list the trust module +# if we only load softhsm (it should as trust modules +# are always loaded).ould list them both + +nr=$(${P11TOOL} --list-tokens|grep -c ^Token) +if test "$nr" != 2;then + echo "Error: did not find 2 modules" + ${P11TOOL} --list-tokens +fi + + +# Check whether both modules are found when gnutls_pkcs11_init +# is not called but a pkcs11 operation is called. +${builddir}/pkcs11/list-tokens -d|wc -l +if test "$nr" != 2;then + echo "Error in test 1: did not find 2 modules" + ${builddir}/pkcs11/list-tokens -d +fi + +# Check whether both modules are found when gnutls_pkcs11_init +# is called with the auto flag +${builddir}/pkcs11/list-tokens -a|wc -l +if test "$nr" != 2;then + echo "Error in test 2: did not find 2 modules" + ${builddir}/pkcs11/list-tokens -a +fi + +# Check whether only trusted modules are listed when the +# trusted flag is given to gnutls_pkcs11_init(). +${builddir}/pkcs11/list-tokens -t|wc -l +if test "$nr" != 1;then + echo "Error in test 3: did not find the trusted module" + ${builddir}/pkcs11/list-tokens -t +fi + +# Check whether only trusted is listed after certificate verification +# is performed. +${builddir}/pkcs11/list-tokens -v|wc -l +if test "$nr" != 1;then + echo "Error in test 4: did not find 1 module" + ${builddir}/pkcs11/list-tokens -v +fi + +# Check whether only trusted is listed when gnutls_pkcs11_init +# is called with manual flag and a certificate verification is performed. +${builddir}/pkcs11/list-tokens -m -v|wc -l +if test "$nr" != 1;then + echo "Error in test 5: did not find 1 module" + ${builddir}/pkcs11/list-tokens -m -v +fi + +exit 0 diff --git a/tests/pkcs11/list-tokens.c b/tests/pkcs11/list-tokens.c new file mode 100644 index 0000000000..a835ef9c60 --- /dev/null +++ b/tests/pkcs11/list-tokens.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2016-2017 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * GnuTLS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuTLS is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include <gnutls/gnutls.h> +#include <gnutls/x509.h> +#include <gnutls/abstract.h> +#include <getopt.h> +#include <assert.h> + +/* lists the registered PKCS#11 modules by p11-kit. + */ + +static void tls_log_func(int level, const char *str) +{ + fprintf(stderr, "|<%d>| %s", level, str); +} + +int +_gnutls_pkcs11_token_get_url(unsigned int seq, + gnutls_pkcs11_url_type_t detailed, char **url, + unsigned flags); + +int main(int argc, char **argv) +{ + int ret; + unsigned i; + int opt; + char *url; + gnutls_certificate_credentials_t cred; + unsigned flag = 1; + + ret = gnutls_global_init(); + if (ret != 0) { + fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret)); + exit(1); + } + + gnutls_global_set_log_function(tls_log_func); + //gnutls_global_set_log_level(4711); + + while((opt = getopt(argc, argv, "mvatd")) != -1) { + switch(opt) { + case 'm': + ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL); + if (ret != 0) { + fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret)); + exit(1); + } + break; + case 'd': + flag = 0; + break; + case 'a': + ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO, NULL); + if (ret != 0) { + fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret)); + exit(1); + } + break; + case 't': + ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_AUTO_TRUSTED, NULL); + if (ret != 0) { + fprintf(stderr, "error at %d: %s\n", __LINE__, gnutls_strerror(ret)); + exit(1); + } + break; + case 'v': + assert(gnutls_certificate_allocate_credentials(&cred) >= 0); + assert(gnutls_certificate_set_x509_system_trust(cred) >= 0); + gnutls_certificate_free_credentials(cred); + break; + default: + fprintf(stderr, "Unknown option %c\n", (char)opt); + exit(1); + } + } + + + for (i=0;;i++) { + ret = _gnutls_pkcs11_token_get_url(i, 0, &url, flag); + if (ret < 0) + break; + printf("%s\n", url); + free(url); + } + + gnutls_global_deinit(); +} |