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:
Tobias Brunner
2017-05-23 18:38:46 +02:00
26 changed files with 380 additions and 41 deletions
+1
View File
@@ -27,6 +27,7 @@ libtool
y.tab.[ch]
lex.yy.c
*keywords.c
plugin_constructors.c
Doxyfile
apidoc/
*~
+4
View File
@@ -1,5 +1,9 @@
SUBDIRS = src man conf init testing
if USE_FUZZING
SUBDIRS += fuzz
endif
if USE_SCRIPTS
SUBDIRS += scripts
endif
+35 -8
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
fuzz_certs
+18
View File
@@ -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)
+40
View File
@@ -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
View File
@@ -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
+9
View File
@@ -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
########################
+7
View File
@@ -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");
+3 -1
View File
@@ -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;
+10
View File
@@ -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
+9 -7
View File
@@ -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)
{
+13
View File
@@ -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))
+3 -3
View File
@@ -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);
+78 -7
View File
@@ -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);
+10
View File
@@ -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_ @}*/
+28 -4
View File
@@ -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;
+9 -4
View File
@@ -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;
}
+1 -1
View File
@@ -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--;
}
+9
View File
@@ -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
########################
+7
View File
@@ -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.
*/
+9
View File
@@ -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
+7
View File
@@ -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.
*/