Merge branch 'fuzzing'
Adds support for fuzzing the certificate parser provided by the default plugins (x509, pem, gmp etc.) on Google's OSS-Fuzz infrastructure (or generally with libFuzzer). Fixes several issues that were found while fuzzing these plugins. When building the libraries monolithically and statically the plugin constructors are now hard-coded in each library so the plugin code is not removed by the linker because it thinks none of their symbols are ever referenced.
This commit is contained in:
@@ -27,6 +27,7 @@ libtool
|
||||
y.tab.[ch]
|
||||
lex.yy.c
|
||||
*keywords.c
|
||||
plugin_constructors.c
|
||||
Doxyfile
|
||||
apidoc/
|
||||
*~
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
SUBDIRS = src man conf init testing
|
||||
|
||||
if USE_FUZZING
|
||||
SUBDIRS += fuzz
|
||||
endif
|
||||
|
||||
if USE_SCRIPTS
|
||||
SUBDIRS += scripts
|
||||
endif
|
||||
|
||||
+35
-8
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2007-2015 Tobias Brunner
|
||||
# Copyright (C) 2007-2017 Tobias Brunner
|
||||
# Copyright (C) 2006-2016 Andreas Steffen
|
||||
# Copyright (C) 2006-2014 Martin Willi
|
||||
# HSR Hochschule fuer Technik Rapperswil
|
||||
@@ -35,6 +35,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])
|
||||
AC_CONFIG_MACRO_DIR([m4/config])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_DEFINE([CONFIG_H_INCLUDED], [], [defined if config.h included])
|
||||
AC_DISABLE_STATIC
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
m4_include(m4/macros/split-package-version.m4)
|
||||
@@ -62,6 +63,7 @@ ARG_WITH_SUBST([routing-table], [220], [set routing table to use for IPsec
|
||||
ARG_WITH_SUBST([routing-table-prio], [220], [set priority for IPsec routing table])
|
||||
ARG_WITH_SUBST([ipsec-script], [ipsec], [change the name of the ipsec script])
|
||||
ARG_WITH_SUBST([fips-mode], [0], [set openssl FIPS mode: disabled(0), enabled(1), Suite B enabled(2)])
|
||||
ARG_WITH_SUBST([libfuzzer], [], [path to libFuzzer.a])
|
||||
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.])
|
||||
@@ -277,6 +279,7 @@ 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([fuzzing], [enable fuzzing scripts (found in directory fuzz).])
|
||||
ARG_ENABL_SET([libipsec], [enable user space IPsec implementation.])
|
||||
ARG_ENABL_SET([manager], [enable web management console (proof of concept).])
|
||||
ARG_ENABL_SET([medcli], [enable mediation client configuration database plugin.])
|
||||
@@ -1295,6 +1298,19 @@ AM_CONDITIONAL(PYTHON_EGGS_INSTALL, [test "x$python_eggs_install" = xtrue])
|
||||
|
||||
AM_CONDITIONAL(PERL_CPAN_INSTALL, [test "x$perl_cpan_install" = xtrue])
|
||||
|
||||
AC_CACHE_CHECK(
|
||||
[if plugin constructors should be resolved statically],
|
||||
[ss_cv_static_plugin_constructors],
|
||||
[if test x$monolithic = xtrue -a x$enable_static = xyes; then
|
||||
ss_cv_static_plugin_constructors=yes
|
||||
else
|
||||
ss_cv_static_plugin_constructors="no (enabled for static, monolithic builds)"
|
||||
fi]
|
||||
)
|
||||
if test "x$ss_cv_static_plugin_constructors" = xyes; then
|
||||
static_plugin_constructors=true
|
||||
fi
|
||||
|
||||
# ===============================================
|
||||
# collect plugin list for strongSwan components
|
||||
# ===============================================
|
||||
@@ -1309,6 +1325,7 @@ attest_plugins=
|
||||
scepclient_plugins=
|
||||
pki_plugins=
|
||||
scripts_plugins=
|
||||
fuzz_plugins=
|
||||
manager_plugins=
|
||||
medsrv_plugins=
|
||||
nm_plugins=
|
||||
@@ -1332,21 +1349,21 @@ ADD_PLUGIN([aes], [s charon scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([des], [s charon scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([blowfish], [s charon scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([rc2], [s charon scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([sha2], [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([sha3], [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([sha1], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([sha2], [s charon scepclient pki scripts medsrv attest nm cmd aikgen fuzz])
|
||||
ADD_PLUGIN([sha3], [s charon scepclient pki scripts medsrv attest nm cmd aikgen fuzz])
|
||||
ADD_PLUGIN([sha1], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen fuzz])
|
||||
ADD_PLUGIN([md4], [s charon scepclient pki nm cmd])
|
||||
ADD_PLUGIN([md5], [s charon scepclient pki scripts attest nm cmd aikgen])
|
||||
ADD_PLUGIN([mgf1], [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([rdrand], [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([random], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([nonce], [s charon nm cmd aikgen])
|
||||
ADD_PLUGIN([x509], [s charon scepclient pki scripts attest nm cmd aikgen])
|
||||
ADD_PLUGIN([x509], [s charon scepclient pki scripts attest nm cmd aikgen fuzz])
|
||||
ADD_PLUGIN([revocation], [s charon pki nm cmd])
|
||||
ADD_PLUGIN([constraints], [s charon nm cmd])
|
||||
ADD_PLUGIN([acert], [s charon])
|
||||
ADD_PLUGIN([pubkey], [s charon cmd aikgen])
|
||||
ADD_PLUGIN([pkcs1], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([pkcs1], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen fuzz])
|
||||
ADD_PLUGIN([pkcs7], [s charon scepclient pki scripts nm cmd])
|
||||
ADD_PLUGIN([pkcs8], [s charon scepclient pki scripts manager medsrv attest nm cmd])
|
||||
ADD_PLUGIN([pkcs12], [s charon scepclient pki scripts cmd])
|
||||
@@ -1355,13 +1372,13 @@ ADD_PLUGIN([dnskey], [s charon pki])
|
||||
ADD_PLUGIN([sshkey], [s charon pki nm cmd])
|
||||
ADD_PLUGIN([dnscert], [c charon])
|
||||
ADD_PLUGIN([ipseckey], [c charon])
|
||||
ADD_PLUGIN([pem], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([pem], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen fuzz])
|
||||
ADD_PLUGIN([padlock], [s charon])
|
||||
ADD_PLUGIN([openssl], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([gcrypt], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([af-alg], [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([fips-prf], [s charon nm cmd])
|
||||
ADD_PLUGIN([gmp], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen])
|
||||
ADD_PLUGIN([gmp], [s charon scepclient pki scripts manager medsrv attest nm cmd aikgen fuzz])
|
||||
ADD_PLUGIN([curve25519], [s charon pki scripts nm cmd])
|
||||
ADD_PLUGIN([agent], [s charon nm cmd])
|
||||
ADD_PLUGIN([keychain], [s charon cmd])
|
||||
@@ -1462,6 +1479,7 @@ AC_SUBST(attest_plugins)
|
||||
AC_SUBST(scepclient_plugins)
|
||||
AC_SUBST(pki_plugins)
|
||||
AC_SUBST(scripts_plugins)
|
||||
AC_SUBST(fuzz_plugins)
|
||||
AC_SUBST(manager_plugins)
|
||||
AC_SUBST(medsrv_plugins)
|
||||
AC_SUBST(nm_plugins)
|
||||
@@ -1646,6 +1664,7 @@ AM_CONDITIONAL(USE_NM, test x$nm = xtrue)
|
||||
AM_CONDITIONAL(USE_PKI, test x$pki = xtrue)
|
||||
AM_CONDITIONAL(USE_SCEPCLIENT, test x$scepclient = xtrue)
|
||||
AM_CONDITIONAL(USE_SCRIPTS, test x$scripts = xtrue)
|
||||
AM_CONDITIONAL(USE_FUZZING, test x$fuzzing = xtrue)
|
||||
AM_CONDITIONAL(USE_CONFTEST, test x$conftest = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$pki = xtrue -o x$scepclient = xtrue -o x$conftest = xtrue -o x$fast = xtrue -o x$imcv = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$tls = xtrue -o x$tnc_tnccs = xtrue -o x$aikgen = xtrue -o x$svc = xtrue -o x$systemd = xtrue)
|
||||
AM_CONDITIONAL(USE_LIBCHARON, test x$charon = xtrue -o x$conftest = xtrue -o x$nm = xtrue -o x$tkm = xtrue -o x$cmd = xtrue -o x$svc = xtrue -o x$systemd = xtrue)
|
||||
@@ -1667,6 +1686,7 @@ AM_CONDITIONAL(USE_IMCV, test x$imcv = xtrue)
|
||||
AM_CONDITIONAL(USE_TROUSERS, test x$tss_trousers = xtrue)
|
||||
AM_CONDITIONAL(USE_TSS2, test x$tss_tss2 = xtrue)
|
||||
AM_CONDITIONAL(MONOLITHIC, test x$monolithic = xtrue)
|
||||
AM_CONDITIONAL(STATIC_PLUGIN_CONSTRUCTORS, test x$static_plugin_constructors = xtrue)
|
||||
AM_CONDITIONAL(USE_SILENT_RULES, test x$enable_silent_rules = xyes)
|
||||
AM_CONDITIONAL(COVERAGE, test x$coverage = xtrue)
|
||||
AM_CONDITIONAL(USE_DBGHELP, test x$dbghelp_backtraces = xtrue)
|
||||
@@ -1698,12 +1718,18 @@ fi
|
||||
if test x$monolithic = xtrue; then
|
||||
AC_DEFINE([MONOLITHIC], [], [monolithic build embedding plugins])
|
||||
fi
|
||||
if test x$static_plugin_constructors = xtrue; then
|
||||
AC_DEFINE([STATIC_PLUGIN_CONSTRUCTORS], [], [static plugin constructors])
|
||||
fi
|
||||
if test x$ikev1 = xtrue; then
|
||||
AC_DEFINE([USE_IKEV1], [], [support for IKEv1 protocol])
|
||||
fi
|
||||
if test x$ikev2 = xtrue; then
|
||||
AC_DEFINE([USE_IKEV2], [], [support for IKEv2 protocol])
|
||||
fi
|
||||
if test x$fuzzing = xtrue; then
|
||||
AC_DEFINE([USE_FUZZING], [], [build code for fuzzing])
|
||||
fi
|
||||
|
||||
# ====================================================
|
||||
# options for enabled modules (see conf/Makefile.am)
|
||||
@@ -1734,6 +1760,7 @@ AC_SUBST(strongswan_options)
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
conf/Makefile
|
||||
fuzz/Makefile
|
||||
man/Makefile
|
||||
init/Makefile
|
||||
init/systemd/Makefile
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
fuzz_certs
|
||||
@@ -0,0 +1,18 @@
|
||||
CPPFLAGS = @CPPFLAGS@ \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
-DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
|
||||
-DPLUGINS="\"${fuzz_plugins}\""
|
||||
|
||||
LDFLAGS = @LDFLAGS@ ${libfuzzer} \
|
||||
$(top_builddir)/src/libstrongswan/.libs/libstrongswan.a \
|
||||
-Wl,-Bstatic -lgmp -Wl,-Bdynamic \
|
||||
-stdlib=libc++ -lstdc++
|
||||
|
||||
FUZZ_TARGETS=fuzz_certs
|
||||
|
||||
all-local: $(FUZZ_TARGETS)
|
||||
|
||||
CLEANFILES=$(FUZZ_TARGETS)
|
||||
|
||||
fuzz_certs: fuzz_certs.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< $(LDFLAGS)
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Tobias Brunner
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program 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 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#include <library.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len)
|
||||
{
|
||||
certificate_t *cert;
|
||||
chunk_t chunk;
|
||||
|
||||
dbg_default_set_level(-1);
|
||||
library_init(NULL, "fuzz_certs");
|
||||
plugin_loader_add_plugindirs(PLUGINDIR, PLUGINS);
|
||||
if (!lib->plugins->load(lib->plugins, PLUGINS))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
chunk = chunk_create((u_char*)buf, len);
|
||||
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
|
||||
BUILD_BLOB, chunk, BUILD_END);
|
||||
DESTROY_IF(cert);
|
||||
|
||||
lib->plugins->unload(lib->plugins);
|
||||
library_deinit();
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -32,7 +32,7 @@ printf-builtin)
|
||||
all|coverage)
|
||||
CONFIG="--enable-all --disable-android-dns --disable-android-log
|
||||
--disable-dumm --disable-kernel-pfroute --disable-keychain
|
||||
--disable-lock-profiler --disable-padlock
|
||||
--disable-lock-profiler --disable-padlock --disable-fuzzing
|
||||
--disable-osx-attr --disable-tkm --disable-uci
|
||||
--disable-systemd --disable-soup --disable-unwind-backtraces
|
||||
--disable-svc --disable-dbghelp-backtraces --disable-socket-win
|
||||
|
||||
@@ -184,6 +184,15 @@ if USE_ME
|
||||
sa/ikev2/tasks/ike_me.c sa/ikev2/tasks/ike_me.h
|
||||
endif
|
||||
|
||||
if STATIC_PLUGIN_CONSTRUCTORS
|
||||
BUILT_SOURCES = $(srcdir)/plugin_constructors.c
|
||||
CLEANFILES = $(srcdir)/plugin_constructors.c
|
||||
|
||||
$(srcdir)/plugin_constructors.c: $(top_srcdir)/src/libstrongswan/plugins/plugin_constructors.py
|
||||
$(AM_V_GEN) \
|
||||
$(PYTHON) $(top_srcdir)/src/libstrongswan/plugins/plugin_constructors.py ${c_plugins} > $@
|
||||
endif
|
||||
|
||||
# build optional plugins
|
||||
########################
|
||||
|
||||
|
||||
@@ -117,6 +117,13 @@ struct private_daemon_t {
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register plugins if built statically
|
||||
*/
|
||||
#ifdef STATIC_PLUGIN_CONSTRUCTORS
|
||||
#include "plugin_constructors.c"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* One and only instance of the daemon.
|
||||
*/
|
||||
|
||||
@@ -55,7 +55,7 @@ struct private_tnc_ifmap_soap_msg_t {
|
||||
static xmlNodePtr find_child(xmlNodePtr parent, const xmlChar* name)
|
||||
{
|
||||
xmlNodePtr child;
|
||||
|
||||
|
||||
child = parent->xmlChildrenNode;
|
||||
while (child)
|
||||
{
|
||||
@@ -80,7 +80,7 @@ METHOD(tnc_ifmap_soap_msg_t, post, bool,
|
||||
xmlChar *xml_str, *errorCode, *errorString;
|
||||
int xml_len, len, written;
|
||||
chunk_t xml, http;
|
||||
char buf[4096];
|
||||
char buf[4096] = { 0 };
|
||||
status_t status;
|
||||
|
||||
DBG2(DBG_TNC, "sending ifmap %s", request->name);
|
||||
@@ -131,7 +131,8 @@ METHOD(tnc_ifmap_soap_msg_t, post, bool,
|
||||
xml = chunk_empty;
|
||||
do
|
||||
{
|
||||
len = this->tls->read(this->tls, buf, sizeof(buf), TRUE);
|
||||
/* reduce size so the buffer is null-terminated */
|
||||
len = this->tls->read(this->tls, buf, sizeof(buf)-1, TRUE);
|
||||
if (len <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
@@ -150,7 +151,7 @@ METHOD(tnc_ifmap_soap_msg_t, post, bool,
|
||||
DBG3(DBG_TNC, "parsing XML message %B", &xml);
|
||||
this->doc = xmlParseMemory(xml.ptr, xml.len);
|
||||
free(xml.ptr);
|
||||
|
||||
|
||||
if (!this->doc)
|
||||
{
|
||||
DBG1(DBG_TNC, "failed to parse XML message");
|
||||
|
||||
@@ -170,6 +170,7 @@ METHOD(pa_tnc_attr_t, process, status_t,
|
||||
chunk_t last_use;
|
||||
uint16_t reserved;
|
||||
struct tm t;
|
||||
char buf[BUF_LEN];
|
||||
|
||||
*offset = 0;
|
||||
|
||||
@@ -208,7 +209,8 @@ METHOD(pa_tnc_attr_t, process, status_t,
|
||||
*offset = 4;
|
||||
|
||||
/* Conversion from RFC 3339 ASCII string to time_t */
|
||||
if (sscanf(last_use.ptr, "%4d-%2d-%2dT%2d:%2d:%2dZ", &t.tm_year, &t.tm_mon,
|
||||
snprintf(buf, sizeof(buf), "%.*s", (int)last_use.len, last_use.ptr);
|
||||
if (sscanf(buf, "%4d-%2d-%2dT%2d:%2d:%2dZ", &t.tm_year, &t.tm_mon,
|
||||
&t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
|
||||
{
|
||||
DBG1(DBG_TNC, "invalid last_use time format in IETF operational status");
|
||||
|
||||
@@ -263,13 +263,15 @@ bool measurement_time_from_utc(time_t *measurement_time, chunk_t utc_time)
|
||||
{
|
||||
int tm_year, tm_mon, tm_day, tm_days, tm_hour, tm_min, tm_sec, tm_secs;
|
||||
int tm_leap_4, tm_leap_100, tm_leap_400, tm_leap;
|
||||
char buf[BUF_LEN];
|
||||
|
||||
if (memeq(utc_undefined_time_str, utc_time.ptr, utc_time.len))
|
||||
{
|
||||
*measurement_time = 0;
|
||||
return TRUE;
|
||||
}
|
||||
if (sscanf(utc_time.ptr, "%4d-%2d-%2dT%2d:%2d:%2dZ",
|
||||
snprintf(buf, sizeof(buf), "%.*s", (int)utc_time.len, utc_time.ptr);
|
||||
if (sscanf(buf, "%4d-%2d-%2dT%2d:%2d:%2dZ",
|
||||
&tm_year, &tm_mon, &tm_day, &tm_hour, &tm_min, &tm_sec) != 6)
|
||||
{
|
||||
return FALSE;
|
||||
|
||||
@@ -195,6 +195,7 @@ endif
|
||||
EXTRA_DIST = \
|
||||
asn1/oid.txt asn1/oid.pl \
|
||||
crypto/proposal/proposal_keywords_static.txt \
|
||||
plugins/plugin_constructors.py \
|
||||
Android.mk
|
||||
|
||||
BUILT_SOURCES = \
|
||||
@@ -220,6 +221,15 @@ $(srcdir)/crypto/proposal/proposal_keywords_static.c: $(srcdir)/crypto/proposal/
|
||||
$(GPERF) -N proposal_get_token_static -m 10 -C -G -c -t -D < \
|
||||
$(srcdir)/crypto/proposal/proposal_keywords_static.txt > $@
|
||||
|
||||
if STATIC_PLUGIN_CONSTRUCTORS
|
||||
BUILT_SOURCES += $(srcdir)/plugin_constructors.c
|
||||
CLEANFILES = $(srcdir)/plugin_constructors.c
|
||||
|
||||
$(srcdir)/plugin_constructors.c: $(srcdir)/plugins/plugin_constructors.py
|
||||
$(AM_V_GEN) \
|
||||
$(PYTHON) $(srcdir)/plugins/plugin_constructors.py ${s_plugins} > $@
|
||||
endif
|
||||
|
||||
if MONOLITHIC
|
||||
SUBDIRS =
|
||||
else
|
||||
|
||||
@@ -350,13 +350,15 @@ time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
|
||||
int tm_leap_4, tm_leap_100, tm_leap_400, tm_leap;
|
||||
int tz_hour, tz_min, tz_offset;
|
||||
time_t tm_days, tm_secs;
|
||||
u_char *eot = NULL;
|
||||
char buf[BUF_LEN], *eot = NULL;
|
||||
|
||||
if ((eot = memchr(utctime->ptr, 'Z', utctime->len)) != NULL)
|
||||
snprintf(buf, sizeof(buf), "%.*s", (int)utctime->len, utctime->ptr);
|
||||
|
||||
if ((eot = strchr(buf, 'Z')) != NULL)
|
||||
{
|
||||
tz_offset = 0; /* Zulu time with a zero time zone offset */
|
||||
}
|
||||
else if ((eot = memchr(utctime->ptr, '+', utctime->len)) != NULL)
|
||||
else if ((eot = strchr(buf, '+')) != NULL)
|
||||
{
|
||||
if (sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min) != 2)
|
||||
{
|
||||
@@ -364,7 +366,7 @@ time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
|
||||
}
|
||||
tz_offset = 3600*tz_hour + 60*tz_min; /* positive time zone offset */
|
||||
}
|
||||
else if ((eot = memchr(utctime->ptr, '-', utctime->len)) != NULL)
|
||||
else if ((eot = strchr(buf, '-')) != NULL)
|
||||
{
|
||||
if (sscanf(eot+1, "%2d%2d", &tz_hour, &tz_min) != 2)
|
||||
{
|
||||
@@ -382,15 +384,15 @@ time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
|
||||
const char* format = (type == ASN1_UTCTIME)? "%2d%2d%2d%2d%2d":
|
||||
"%4d%2d%2d%2d%2d";
|
||||
|
||||
if (sscanf(utctime->ptr, format, &tm_year, &tm_mon, &tm_day,
|
||||
&tm_hour, &tm_min) != 5)
|
||||
if (sscanf(buf, format, &tm_year, &tm_mon, &tm_day,
|
||||
&tm_hour, &tm_min) != 5)
|
||||
{
|
||||
return 0; /* error in [yy]yymmddhhmm time format */
|
||||
}
|
||||
}
|
||||
|
||||
/* is there a seconds field? */
|
||||
if ((eot - utctime->ptr) == ((type == ASN1_UTCTIME)?12:14))
|
||||
if ((eot - buf) == ((type == ASN1_UTCTIME)?12:14))
|
||||
{
|
||||
if (sscanf(eot-2, "%2d", &tm_sec) != 1)
|
||||
{
|
||||
|
||||
@@ -93,6 +93,13 @@ void library_add_namespace(char *ns)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register plugins if built statically
|
||||
*/
|
||||
#ifdef STATIC_PLUGIN_CONSTRUCTORS
|
||||
#include "plugin_constructors.c"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* library instance
|
||||
*/
|
||||
@@ -241,6 +248,8 @@ static bool equals(char *a, char *b)
|
||||
*/
|
||||
#define MEMWIPE_WIPE_WORDS 16
|
||||
|
||||
#ifndef NO_CHECK_MEMWIPE
|
||||
|
||||
/**
|
||||
* Write magic to memory, and try to clear it with memwipe()
|
||||
*/
|
||||
@@ -281,6 +290,8 @@ static bool check_memwipe()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* see header file
|
||||
*/
|
||||
@@ -387,10 +398,12 @@ bool library_init(char *settings, const char *namespace)
|
||||
this->public.streams = stream_manager_create();
|
||||
this->public.plugins = plugin_loader_create();
|
||||
|
||||
#ifndef NO_CHECK_MEMWIPE
|
||||
if (!check_memwipe())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lib->settings->get_bool(lib->settings,
|
||||
"%s.integrity_test", FALSE, lib->ns))
|
||||
|
||||
@@ -61,7 +61,7 @@ static bool find_boundary(char* tag, chunk_t *line)
|
||||
|
||||
if (!present("-----", line) ||
|
||||
!present(tag, line) ||
|
||||
*line->ptr != ' ')
|
||||
!line->len || *line->ptr != ' ')
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@@ -250,7 +250,7 @@ static status_t pem_to_bin(chunk_t *blob, bool *pgp)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (match("Proc-Type", &name) && *value.ptr == '4')
|
||||
if (match("Proc-Type", &name) && value.len && *value.ptr == '4')
|
||||
{
|
||||
encrypted = TRUE;
|
||||
}
|
||||
@@ -306,7 +306,7 @@ static status_t pem_to_bin(chunk_t *blob, bool *pgp)
|
||||
}
|
||||
|
||||
/* check for PGP armor checksum */
|
||||
if (*data.ptr == '=')
|
||||
if (data.len && *data.ptr == '=')
|
||||
{
|
||||
*pgp = TRUE;
|
||||
data.ptr++;
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (C) 2017 Tobias Brunner
|
||||
# HSR Hochschule fuer Technik Rapperswil
|
||||
#
|
||||
# This program 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 2 of the License, or (at your
|
||||
# option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
#
|
||||
# This program 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.
|
||||
|
||||
import sys
|
||||
from argparse import ArgumentParser
|
||||
|
||||
def generate_output(plugins):
|
||||
"""Generate a source file containing plugin constructor registrations"""
|
||||
print("/**")
|
||||
print(" * Register plugin constructors for static libraries")
|
||||
print(" * Created by {0}".format(__file__))
|
||||
print(" */")
|
||||
print("")
|
||||
print("#include <plugins/plugin.h>")
|
||||
print("#include <plugins/plugin_loader.h>")
|
||||
print("")
|
||||
|
||||
for plugin in plugins:
|
||||
print("plugin_t *{0}_plugin_create();".format(plugin.replace('-', '_')))
|
||||
|
||||
print("")
|
||||
print("static void register_plugins() __attribute__ ((constructor));")
|
||||
print("static void register_plugins()")
|
||||
print("{")
|
||||
|
||||
for plugin in plugins:
|
||||
print(' plugin_constructor_register("{0}", {1}_plugin_create);'.format(plugin, plugin.replace('-', '_')))
|
||||
|
||||
print("}")
|
||||
|
||||
print("")
|
||||
print("static void unregister_plugins() __attribute__ ((destructor));")
|
||||
print("static void unregister_plugins()")
|
||||
print("{")
|
||||
|
||||
for plugin in plugins:
|
||||
print(' plugin_constructor_register("{0}", NULL);'.format(plugin))
|
||||
|
||||
print("}")
|
||||
print("")
|
||||
|
||||
parser = ArgumentParser(description = "Generate constructor registration for a list of plugins")
|
||||
parser.add_argument('plugins', metavar="plugin", nargs="*",
|
||||
help = "name of a plugin for which to generate constructor registration")
|
||||
|
||||
|
||||
args = parser.parse_args()
|
||||
generate_output(args.plugins);
|
||||
@@ -40,6 +40,13 @@ typedef struct registered_feature_t registered_feature_t;
|
||||
typedef struct provided_feature_t provided_feature_t;
|
||||
typedef struct plugin_entry_t plugin_entry_t;
|
||||
|
||||
#ifdef STATIC_PLUGIN_CONSTRUCTORS
|
||||
/**
|
||||
* Statically registered constructors
|
||||
*/
|
||||
static hashtable_t *plugin_constructors = NULL;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* private data of plugin_loader
|
||||
*/
|
||||
@@ -298,6 +305,46 @@ static plugin_t *static_features_create(const char *name,
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
#ifdef STATIC_PLUGIN_CONSTRUCTORS
|
||||
/*
|
||||
* Described in header.
|
||||
*/
|
||||
void plugin_constructor_register(char *name, void *constructor)
|
||||
{
|
||||
bool old = FALSE;
|
||||
|
||||
if (lib && lib->leak_detective)
|
||||
{
|
||||
old = lib->leak_detective->set_state(lib->leak_detective, FALSE);
|
||||
}
|
||||
|
||||
if (!plugin_constructors)
|
||||
{
|
||||
chunk_hash_seed();
|
||||
plugin_constructors = hashtable_create(hashtable_hash_str,
|
||||
hashtable_equals_str, 32);
|
||||
}
|
||||
if (constructor)
|
||||
{
|
||||
plugin_constructors->put(plugin_constructors, name, constructor);
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin_constructors->remove(plugin_constructors, name);
|
||||
if (!plugin_constructors->get_count(plugin_constructors))
|
||||
{
|
||||
plugin_constructors->destroy(plugin_constructors);
|
||||
plugin_constructors = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (lib && lib->leak_detective)
|
||||
{
|
||||
lib->leak_detective->set_state(lib->leak_detective, old);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* create a plugin
|
||||
* returns: NOT_FOUND, if the constructor was not found
|
||||
@@ -309,7 +356,7 @@ static status_t create_plugin(private_plugin_loader_t *this, void *handle,
|
||||
{
|
||||
char create[128];
|
||||
plugin_t *plugin;
|
||||
plugin_constructor_t constructor;
|
||||
plugin_constructor_t constructor = NULL;
|
||||
|
||||
if (snprintf(create, sizeof(create), "%s_plugin_create",
|
||||
name) >= sizeof(create))
|
||||
@@ -317,8 +364,17 @@ static status_t create_plugin(private_plugin_loader_t *this, void *handle,
|
||||
return FAILED;
|
||||
}
|
||||
translate(create, "-", "_");
|
||||
constructor = dlsym(handle, create);
|
||||
if (constructor == NULL)
|
||||
#ifdef STATIC_PLUGIN_CONSTRUCTORS
|
||||
if (plugin_constructors)
|
||||
{
|
||||
constructor = plugin_constructors->get(plugin_constructors, name);
|
||||
}
|
||||
if (!constructor)
|
||||
#endif
|
||||
{
|
||||
constructor = dlsym(handle, create);
|
||||
}
|
||||
if (!constructor)
|
||||
{
|
||||
return NOT_FOUND;
|
||||
}
|
||||
@@ -674,9 +730,11 @@ static bool load_dependencies(private_plugin_loader_t *this,
|
||||
|
||||
if (!find_compatible_feature(this, &provided->feature[i]))
|
||||
{
|
||||
char *name, *provide, *depend;
|
||||
bool soft = provided->feature[i].kind == FEATURE_SDEPEND;
|
||||
|
||||
#ifndef USE_FUZZING
|
||||
char *name, *provide, *depend;
|
||||
|
||||
name = provided->entry->plugin->get_name(provided->entry->plugin);
|
||||
provide = plugin_feature_get_string(&provided->feature[0]);
|
||||
depend = plugin_feature_get_string(&provided->feature[i]);
|
||||
@@ -697,6 +755,8 @@ static bool load_dependencies(private_plugin_loader_t *this,
|
||||
}
|
||||
free(provide);
|
||||
free(depend);
|
||||
#endif /* !USE_FUZZING */
|
||||
|
||||
if (soft)
|
||||
{ /* it's ok if we can't resolve soft dependencies */
|
||||
continue;
|
||||
@@ -716,8 +776,6 @@ static void load_feature(private_plugin_loader_t *this,
|
||||
{
|
||||
if (load_dependencies(this, provided, level))
|
||||
{
|
||||
char *name, *provide;
|
||||
|
||||
if (plugin_feature_load(provided->entry->plugin, provided->feature,
|
||||
provided->reg))
|
||||
{
|
||||
@@ -727,6 +785,9 @@ static void load_feature(private_plugin_loader_t *this,
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef USE_FUZZING
|
||||
char *name, *provide;
|
||||
|
||||
name = provided->entry->plugin->get_name(provided->entry->plugin);
|
||||
provide = plugin_feature_get_string(&provided->feature[0]);
|
||||
if (provided->entry->critical)
|
||||
@@ -740,6 +801,7 @@ static void load_feature(private_plugin_loader_t *this,
|
||||
provide, name);
|
||||
}
|
||||
free(provide);
|
||||
#endif /* !USE_FUZZING */
|
||||
}
|
||||
else
|
||||
{ /* TODO: we could check the current level and set a different flag when
|
||||
@@ -759,13 +821,16 @@ static void load_provided(private_plugin_loader_t *this,
|
||||
provided_feature_t *provided,
|
||||
int level)
|
||||
{
|
||||
char *name, *provide;
|
||||
int indent = level * 2;
|
||||
|
||||
if (provided->loaded || provided->failed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef USE_FUZZING
|
||||
char *name, *provide;
|
||||
|
||||
name = provided->entry->plugin->get_name(provided->entry->plugin);
|
||||
provide = plugin_feature_get_string(provided->feature);
|
||||
if (provided->loading)
|
||||
@@ -778,6 +843,12 @@ static void load_provided(private_plugin_loader_t *this,
|
||||
DBG3(DBG_LIB, "%*sloading feature %s in plugin '%s'",
|
||||
indent, "", provide, name);
|
||||
free(provide);
|
||||
#else
|
||||
if (provided->loading)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif /* USE_FUZZING */
|
||||
|
||||
provided->loading = TRUE;
|
||||
load_feature(this, provided, level + 1);
|
||||
|
||||
@@ -168,4 +168,14 @@ plugin_loader_t *plugin_loader_create();
|
||||
*/
|
||||
void plugin_loader_add_plugindirs(char *basedir, char *plugins);
|
||||
|
||||
#ifdef STATIC_PLUGIN_CONSTRUCTORS
|
||||
/**
|
||||
* Register a plugin constructor in case of static builds.
|
||||
*
|
||||
* @param name name of the plugin
|
||||
* @param constructor constructor to register (set to NULL to unregister)
|
||||
*/
|
||||
void plugin_constructor_register(char *name, void *constructor);
|
||||
#endif
|
||||
|
||||
#endif /** PLUGIN_LOADER_H_ @}*/
|
||||
|
||||
@@ -217,6 +217,29 @@ struct private_x509_cert_t {
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert a generalName to a string
|
||||
*/
|
||||
static bool gn_to_string(identification_t *id, char **uri)
|
||||
{
|
||||
int len;
|
||||
|
||||
#ifdef USE_FUZZING
|
||||
chunk_t proper;
|
||||
chunk_printable(id->get_encoding(id), &proper, '?');
|
||||
len = asprintf(uri, "%.*s", (int)proper.len, proper.ptr);
|
||||
chunk_free(&proper);
|
||||
#else
|
||||
len = asprintf(uri, "%Y", id);
|
||||
#endif
|
||||
if (!len)
|
||||
{
|
||||
free(*uri);
|
||||
return FALSE;
|
||||
}
|
||||
return len > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a CertificateDistributionPoint
|
||||
*/
|
||||
@@ -649,7 +672,7 @@ static bool parse_authorityInfoAccess(chunk_t blob, int level0,
|
||||
}
|
||||
DBG2(DBG_ASN, " '%Y'", id);
|
||||
if (accessMethod == OID_OCSP &&
|
||||
asprintf(&uri, "%Y", id) > 0)
|
||||
gn_to_string(id, &uri))
|
||||
{
|
||||
this->ocsp_uris->insert_last(this->ocsp_uris, uri);
|
||||
}
|
||||
@@ -821,7 +844,7 @@ static void add_cdps(linked_list_t *list, linked_list_t *uris,
|
||||
|
||||
while (uris->remove_last(uris, (void**)&id) == SUCCESS)
|
||||
{
|
||||
if (asprintf(&uri, "%Y", id) > 0)
|
||||
if (gn_to_string(id, &uri))
|
||||
{
|
||||
if (issuers->get_count(issuers))
|
||||
{
|
||||
@@ -900,8 +923,8 @@ bool x509_parse_crlDistributionPoints(chunk_t blob, int level0,
|
||||
|
||||
end:
|
||||
parser->destroy(parser);
|
||||
uris->destroy(uris);
|
||||
issuers->destroy(issuers);
|
||||
uris->destroy_offset(uris, offsetof(identification_t, destroy));
|
||||
issuers->destroy_offset(issuers, offsetof(identification_t, destroy));
|
||||
|
||||
return success;
|
||||
}
|
||||
@@ -1461,6 +1484,7 @@ static bool parse_certificate(private_x509_cert_t *this)
|
||||
}
|
||||
break;
|
||||
case OID_AUTHORITY_KEY_ID:
|
||||
chunk_free(&this->authKeyIdentifier);
|
||||
this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(
|
||||
object, level, &this->authKeySerialNumber);
|
||||
break;
|
||||
|
||||
@@ -429,7 +429,15 @@ METHOD(processor_t, execute_job, void,
|
||||
METHOD(processor_t, set_threads, void,
|
||||
private_processor_t *this, u_int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
for (i = 0; i < JOB_PRIO_MAX; i++)
|
||||
{
|
||||
this->prio_threads[i] = lib->settings->get_int(lib->settings,
|
||||
"%s.processor.priority_threads.%N", 0, lib->ns,
|
||||
job_priority_names, i);
|
||||
}
|
||||
if (count > this->total_threads)
|
||||
{ /* increase thread count */
|
||||
worker_thread_t *worker;
|
||||
@@ -551,13 +559,10 @@ processor_t *processor_create()
|
||||
.job_added = condvar_create(CONDVAR_TYPE_DEFAULT),
|
||||
.thread_terminated = condvar_create(CONDVAR_TYPE_DEFAULT),
|
||||
);
|
||||
|
||||
for (i = 0; i < JOB_PRIO_MAX; i++)
|
||||
{
|
||||
this->jobs[i] = linked_list_create();
|
||||
this->prio_threads[i] = lib->settings->get_int(lib->settings,
|
||||
"%s.processor.priority_threads.%N", 0, lib->ns,
|
||||
job_priority_names, i);
|
||||
}
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -643,7 +643,7 @@ chunk_t chunk_from_base64(chunk_t base64, char *buf)
|
||||
outlen += 3;
|
||||
for (j = 0; j < 4; j++)
|
||||
{
|
||||
if (*pos == '=')
|
||||
if (*pos == '=' && outlen > 0)
|
||||
{
|
||||
outlen--;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,15 @@ tnc/tnccs/tnccs_manager.h tnc/tnccs/tnccs_manager.c
|
||||
|
||||
EXTRA_DIST = Android.mk
|
||||
|
||||
if STATIC_PLUGIN_CONSTRUCTORS
|
||||
BUILT_SOURCES = $(srcdir)/plugin_constructors.c
|
||||
CLEANFILES = $(srcdir)/plugin_constructors.c
|
||||
|
||||
$(srcdir)/plugin_constructors.c: $(top_srcdir)/src/libstrongswan/plugins/plugin_constructors.py
|
||||
$(AM_V_GEN) \
|
||||
$(PYTHON) $(top_srcdir)/src/libstrongswan/plugins/plugin_constructors.py ${t_plugins} > $@
|
||||
endif
|
||||
|
||||
# build optional plugins
|
||||
########################
|
||||
|
||||
|
||||
@@ -54,6 +54,13 @@ struct private_tnc_t {
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register plugins if built statically
|
||||
*/
|
||||
#ifdef STATIC_PLUGIN_CONSTRUCTORS
|
||||
#include "plugin_constructors.c"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Single instance of tnc_t.
|
||||
*/
|
||||
|
||||
@@ -33,6 +33,15 @@ else
|
||||
SUBDIRS = .
|
||||
endif
|
||||
|
||||
if STATIC_PLUGIN_CONSTRUCTORS
|
||||
BUILT_SOURCES = $(srcdir)/plugin_constructors.c
|
||||
CLEANFILES = $(srcdir)/plugin_constructors.c
|
||||
|
||||
$(srcdir)/plugin_constructors.c: $(top_srcdir)/src/libstrongswan/plugins/plugin_constructors.py
|
||||
$(AM_V_GEN) \
|
||||
$(PYTHON) $(top_srcdir)/src/libstrongswan/plugins/plugin_constructors.py ${p_plugins} > $@
|
||||
endif
|
||||
|
||||
if USE_TPM
|
||||
SUBDIRS += plugins/tpm
|
||||
if MONOLITHIC
|
||||
|
||||
@@ -17,6 +17,13 @@
|
||||
#include "tpm_tss_tss2.h"
|
||||
#include "tpm_tss_trousers.h"
|
||||
|
||||
/**
|
||||
* Register plugins if built statically
|
||||
*/
|
||||
#ifdef STATIC_PLUGIN_CONSTRUCTORS
|
||||
#include "plugin_constructors.c"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user