aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2016-09-20 16:26:58 +0200
committerTobias Brunner <tobias@strongswan.org>2016-09-20 16:26:58 +0200
commitf654324e5e317ad6b9290c73aec113fc4001b362 (patch)
tree9563d3259b054385a7fb7fa32c853e1290bde404 /src
parentd344474b3d44d55b488140a2d9cd7f8f28ed514e (diff)
parent95f9fa82d5574f08dca873941115ce60c8f14341 (diff)
downloadstrongswan-f654324e5e317ad6b9290c73aec113fc4001b362.tar.bz2
strongswan-f654324e5e317ad6b9290c73aec113fc4001b362.tar.xz
Merge branch 'testing-leak-detective'
Test scenarios now fail if any leaks are detected by the leak detective. Several leaks found this way have been fixed.
Diffstat (limited to 'src')
-rw-r--r--src/charon-tkm/build_common.gpr3
-rw-r--r--src/charon-tkm/src/charon-tkm.c3
-rw-r--r--src/libcharon/plugins/dnscert/dnscert_cred.c19
-rw-r--r--src/libcharon/plugins/eap_peap/eap_peap_server.c4
-rw-r--r--src/libcharon/plugins/ipseckey/ipseckey_cred.c28
-rw-r--r--src/libstrongswan/library.c46
-rw-r--r--src/libstrongswan/plugins/unbound/unbound_response.c3
-rw-r--r--src/libstrongswan/plugins/unbound/unbound_rr.c2
-rw-r--r--src/libstrongswan/utils/leak_detective.c24
-rw-r--r--src/pool/pool.c59
10 files changed, 132 insertions, 59 deletions
diff --git a/src/charon-tkm/build_common.gpr b/src/charon-tkm/build_common.gpr
index 102f6b7a2..459519564 100644
--- a/src/charon-tkm/build_common.gpr
+++ b/src/charon-tkm/build_common.gpr
@@ -9,7 +9,8 @@ project Build_Common is
C_Compiler_Switches := ("-W",
"-Wall",
- "-Wno-unused-parameter");
+ "-Wno-unused-parameter",
+ "-g");
Ada_Compiler_Switches := ("-gnatwale",
"-gnatygAdISuxo",
"-gnata",
diff --git a/src/charon-tkm/src/charon-tkm.c b/src/charon-tkm/src/charon-tkm.c
index 13352e55a..3136b8083 100644
--- a/src/charon-tkm/src/charon-tkm.c
+++ b/src/charon-tkm/src/charon-tkm.c
@@ -373,6 +373,7 @@ int main(int argc, char *argv[])
run();
unlink_pidfile();
+ free(pidfile_name);
status = 0;
charon->bus->remove_listener(charon->bus, &listener->listener);
listener->destroy(listener);
@@ -382,7 +383,7 @@ int main(int argc, char *argv[])
deinit:
destroy_dh_mapping();
libcharon_deinit();
- library_deinit();
tkm_deinit();
+ library_deinit();
return status;
}
diff --git a/src/libcharon/plugins/dnscert/dnscert_cred.c b/src/libcharon/plugins/dnscert/dnscert_cred.c
index 790252682..d32794c99 100644
--- a/src/libcharon/plugins/dnscert/dnscert_cred.c
+++ b/src/libcharon/plugins/dnscert/dnscert_cred.c
@@ -70,6 +70,8 @@ typedef struct {
enumerator_t *inner;
/** response of the DNS resolver which contains the CERTs */
resolver_response_t *response;
+ /** most recently enumerated certificate */
+ certificate_t *cert;
} cert_enumerator_t;
METHOD(enumerator_t, cert_enumerator_enumerate, bool,
@@ -101,17 +103,17 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool,
/* Try to parse PEM certificate container. Both x509 and PGP should
* presumably come as PEM encoded certs. */
certificate = cur_crt->get_certificate(cur_crt);
- *cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_ANY,
- BUILD_BLOB_PEM, certificate,
- BUILD_END);
- if (*cert == NULL)
+ DESTROY_IF(this->cert);
+ this->cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_ANY,
+ BUILD_BLOB_PEM, certificate,
+ BUILD_END);
+ cur_crt->destroy(cur_crt);
+ if (!this->cert)
{
- DBG1(DBG_CFG, " unable to parse certificate, skipping",
- cur_crt->get_cert_type(cur_crt));
- cur_crt->destroy(cur_crt);
+ DBG1(DBG_CFG, " unable to parse certificate, skipping");
continue;
}
- cur_crt->destroy(cur_crt);
+ *cert = this->cert;
return TRUE;
}
return FALSE;
@@ -120,6 +122,7 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool,
METHOD(enumerator_t, cert_enumerator_destroy, void,
cert_enumerator_t *this)
{
+ DESTROY_IF(this->cert);
this->inner->destroy(this->inner);
this->response->destroy(this->response);
free(this);
diff --git a/src/libcharon/plugins/eap_peap/eap_peap_server.c b/src/libcharon/plugins/eap_peap/eap_peap_server.c
index 7f8348e06..d51d0d090 100644
--- a/src/libcharon/plugins/eap_peap/eap_peap_server.c
+++ b/src/libcharon/plugins/eap_peap/eap_peap_server.c
@@ -211,7 +211,7 @@ METHOD(tls_application_t, process, status_t,
{
DBG1(DBG_IKE, "received tunneled EAP-PEAP AVP [EAP/%N]",
eap_code_short_names, code);
-
+ in->destroy(in);
/* if EAP_SUCCESS check if to continue phase2 with EAP-TNC */
return (this->phase2_result == EAP_SUCCESS && code == EAP_SUCCESS) ?
start_phase2_tnc(this) : FAILED;
@@ -250,6 +250,7 @@ METHOD(tls_application_t, process, status_t,
{
DBG1(DBG_IKE, "%N method not available",
eap_type_names, EAP_IDENTITY);
+ in->destroy(in);
return FAILED;
}
}
@@ -258,6 +259,7 @@ METHOD(tls_application_t, process, status_t,
{
DBG1(DBG_IKE, "%N method failed", eap_type_names, EAP_IDENTITY);
+ in->destroy(in);
return FAILED;
}
diff --git a/src/libcharon/plugins/ipseckey/ipseckey_cred.c b/src/libcharon/plugins/ipseckey/ipseckey_cred.c
index 6c041ce26..ff50d8a17 100644
--- a/src/libcharon/plugins/ipseckey/ipseckey_cred.c
+++ b/src/libcharon/plugins/ipseckey/ipseckey_cred.c
@@ -57,6 +57,8 @@ typedef struct {
time_t notAfter;
/* identity to which the IPSECKEY belongs */
identification_t *identity;
+ /** most recently enumerated certificate */
+ certificate_t *cert;
} cert_enumerator_t;
METHOD(enumerator_t, cert_enumerator_enumerate, bool,
@@ -91,28 +93,27 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool,
public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
BUILD_BLOB_DNSKEY, key,
BUILD_END);
+ cur_ipseckey->destroy(cur_ipseckey);
if (!public)
{
DBG1(DBG_CFG, " failed to create public key from IPSECKEY");
- cur_ipseckey->destroy(cur_ipseckey);
continue;
}
-
- *cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
- CERT_TRUSTED_PUBKEY,
- BUILD_PUBLIC_KEY, public,
- BUILD_SUBJECT, this->identity,
- BUILD_NOT_BEFORE_TIME, this->notBefore,
- BUILD_NOT_AFTER_TIME, this->notAfter,
- BUILD_END);
- if (*cert == NULL)
+ DESTROY_IF(this->cert);
+ this->cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
+ CERT_TRUSTED_PUBKEY,
+ BUILD_PUBLIC_KEY, public,
+ BUILD_SUBJECT, this->identity,
+ BUILD_NOT_BEFORE_TIME, this->notBefore,
+ BUILD_NOT_AFTER_TIME, this->notAfter,
+ BUILD_END);
+ public->destroy(public);
+ if (!this->cert)
{
DBG1(DBG_CFG, " failed to create certificate from IPSECKEY");
- cur_ipseckey->destroy(cur_ipseckey);
- public->destroy(public);
continue;
}
- cur_ipseckey->destroy(cur_ipseckey);
+ *cert = this->cert;
return TRUE;
}
return FALSE;
@@ -121,6 +122,7 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool,
METHOD(enumerator_t, cert_enumerator_destroy, void,
cert_enumerator_t *this)
{
+ DESTROY_IF(this->cert);
this->inner->destroy(this->inner);
this->response->destroy(this->response);
free(this);
diff --git a/src/libstrongswan/library.c b/src/libstrongswan/library.c
index e130b93ee..f694509d1 100644
--- a/src/libstrongswan/library.c
+++ b/src/libstrongswan/library.c
@@ -55,6 +55,13 @@ struct private_library_t {
*/
bool integrity_failed;
+#ifdef LEAK_DETECTIVE
+ /**
+ * Where to write leak detective output to
+ */
+ FILE *ld_out;
+#endif
+
/**
* Number of times we have been initialized
*/
@@ -95,32 +102,34 @@ library_t *lib = NULL;
/**
* Default leak report callback
*/
-static void report_leaks(void *user, int count, size_t bytes,
- backtrace_t *bt, bool detailed)
+CALLBACK(report_leaks, void,
+ private_library_t *this, int count, size_t bytes, backtrace_t *bt,
+ bool detailed)
{
- fprintf(stderr, "%zu bytes total, %d allocations, %zu bytes average:\n",
+ fprintf(this->ld_out, "%zu bytes total, %d allocations, %zu bytes average:\n",
bytes, count, bytes / count);
- bt->log(bt, stderr, detailed);
+ bt->log(bt, this->ld_out, detailed);
}
/**
* Default leak report summary callback
*/
-static void sum_leaks(void* user, int count, size_t bytes, int whitelisted)
+CALLBACK(sum_leaks, void,
+ private_library_t *this, int count, size_t bytes, int whitelisted)
{
switch (count)
{
case 0:
- fprintf(stderr, "No leaks detected");
+ fprintf(this->ld_out, "No leaks detected");
break;
case 1:
- fprintf(stderr, "One leak detected");
+ fprintf(this->ld_out, "One leak detected");
break;
default:
- fprintf(stderr, "%d leaks detected, %zu bytes", count, bytes);
+ fprintf(this->ld_out, "%d leaks detected, %zu bytes", count, bytes);
break;
}
- fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted);
+ fprintf(this->ld_out, ", %d suppressed by whitelist\n", whitelisted);
}
#endif /* LEAK_DETECTIVE */
@@ -166,12 +175,18 @@ void library_deinit()
this->public.integrity->destroy(this->public.integrity);
}
+#ifdef LEAK_DETECTIVE
if (lib->leak_detective)
{
lib->leak_detective->report(lib->leak_detective, detailed);
lib->leak_detective->destroy(lib->leak_detective);
lib->leak_detective = NULL;
}
+ if (this->ld_out && this->ld_out != stderr)
+ {
+ fclose(this->ld_out);
+ }
+#endif /* LEAK_DETECTIVE */
backtrace_deinit();
arrays_deinit();
@@ -301,11 +316,22 @@ bool library_init(char *settings, const char *namespace)
backtrace_init();
#ifdef LEAK_DETECTIVE
+ {
+ FILE *out = NULL;
+ char *log;
+
+ log = getenv("LEAK_DETECTIVE_LOG");
+ if (log)
+ {
+ out = fopen(log, "a");
+ }
+ this->ld_out = out ?: stderr;
+ }
lib->leak_detective = leak_detective_create();
if (lib->leak_detective)
{
lib->leak_detective->set_report_cb(lib->leak_detective,
- report_leaks, sum_leaks, NULL);
+ report_leaks, sum_leaks, this);
}
#endif /* LEAK_DETECTIVE */
diff --git a/src/libstrongswan/plugins/unbound/unbound_response.c b/src/libstrongswan/plugins/unbound/unbound_response.c
index 6f6c25e89..950df344c 100644
--- a/src/libstrongswan/plugins/unbound/unbound_response.c
+++ b/src/libstrongswan/plugins/unbound/unbound_response.c
@@ -189,7 +189,7 @@ unbound_response_t *unbound_response_create_frm_libub_response(
*/
rr_list = linked_list_create();
- orig_rr_list = ldns_pkt_get_section_clone(dns_pkt, LDNS_SECTION_ANSWER);
+ orig_rr_list = ldns_pkt_answer(dns_pkt);
orig_rr_count = ldns_rr_list_rr_count(orig_rr_list);
for (i = 0; i < orig_rr_count; i++)
@@ -253,7 +253,6 @@ unbound_response_t *unbound_response_create_frm_libub_response(
this->rr_set = rr_set_create(rr_list, rrsig_list);
ldns_pkt_free(dns_pkt);
- ldns_rr_list_free(orig_rr_list);
}
return &this->public;
}
diff --git a/src/libstrongswan/plugins/unbound/unbound_rr.c b/src/libstrongswan/plugins/unbound/unbound_rr.c
index fc69eed00..91b5cdb33 100644
--- a/src/libstrongswan/plugins/unbound/unbound_rr.c
+++ b/src/libstrongswan/plugins/unbound/unbound_rr.c
@@ -154,11 +154,13 @@ unbound_rr_t *unbound_rr_create_frm_ldns_rr(ldns_rr *rr)
if (status != LDNS_STATUS_OK)
{
DBG1(DBG_LIB, "failed to get the RDATA field of a DNS RR");
+ ldns_buffer_free(buf);
_destroy(this);
return NULL;
}
this->rdata = ldns_buffer_export(buf);
+ ldns_buffer_free(buf);
return &this->public;
}
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index d0f646c31..ad67c0380 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -494,7 +494,7 @@ static bool register_hooks()
* List of functions using static allocation buffers or should be suppressed
* otherwise on leak report.
*/
-char *whitelist[] = {
+static char *whitelist[] = {
/* backtraces, including own */
"backtrace_create",
"strerror_safe",
@@ -551,6 +551,15 @@ char *whitelist[] = {
"xmlInitParserCtxt",
/* libcurl */
"Curl_client_write",
+ /* libsoup */
+ "soup_message_headers_append",
+ "soup_message_headers_clear",
+ "soup_message_headers_get_list",
+ "soup_message_headers_get_one",
+ "soup_session_abort",
+ "soup_session_get_type",
+ /* libldap */
+ "ldap_int_initialize",
/* ClearSilver */
"nerr_init",
/* libgcrypt */
@@ -575,17 +584,28 @@ char *whitelist[] = {
/* libapr */
"apr_pool_create_ex",
/* glib */
+ "g_output_stream_write",
+ "g_resolver_lookup_by_name",
+ "g_signal_connect_data",
+ "g_socket_connection_factory_lookup_type",
"g_type_init_with_debug_flags",
"g_type_register_static",
"g_type_class_ref",
"g_type_create_instance",
"g_type_add_interface_static",
"g_type_interface_add_prerequisite",
- "g_socket_connection_factory_lookup_type",
+ "g_private_set",
+ "g_queue_pop_tail",
/* libgpg */
"gpg_err_init",
/* gnutls */
"gnutls_global_init",
+ /* Ada runtime */
+ "system__tasking__initialize",
+ "system__tasking__initialization__abort_defer",
+ "system__tasking__stages__create_task",
+ /* in case external threads call into our code */
+ "thread_current_id",
};
/**
diff --git a/src/pool/pool.c b/src/pool/pool.c
index 265974860..cd9fb6293 100644
--- a/src/pool/pool.c
+++ b/src/pool/pool.c
@@ -1,6 +1,7 @@
/*
+ * Copyright (C) 2011-2016 Tobias Brunner
* Copyright (C) 2008 Martin Willi
- * Hochschule fuer Technik Rapperswil
+ * 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
@@ -23,6 +24,7 @@
#include <utils/debug.h>
#include <library.h>
+#include <collections/array.h>
#include <networking/host.h>
#include <utils/identification.h>
#include <attributes/attributes.h>
@@ -586,11 +588,11 @@ static void resize(char *name, host_t *end)
/**
* create the lease query using the filter string
*/
-static enumerator_t *create_lease_query(char *filter)
+static enumerator_t *create_lease_query(char *filter, array_t **to_free)
{
enumerator_t *query;
- identification_t *id = NULL;
- host_t *addr = NULL;
+ chunk_t id_chunk = chunk_empty, addr_chunk = chunk_empty;
+ id_type_t id_type = 0;
u_int tstamp = 0;
bool online = FALSE, valid = FALSE, expired = FALSE;
char *value, *pos, *pool = NULL;
@@ -635,18 +637,29 @@ static enumerator_t *create_lease_query(char *filter)
case FIL_ID:
if (value)
{
+ identification_t *id;
+
id = identification_create_from_string(value);
+ id_type = id->get_type(id);
+ id_chunk = chunk_clone(id->get_encoding(id));
+ array_insert_create(to_free, ARRAY_TAIL, id_chunk.ptr);
+ id->destroy(id);
}
break;
case FIL_ADDR:
if (value)
{
+ host_t *addr;
+
addr = host_create_from_string(value, 0);
- }
- if (!addr)
- {
- fprintf(stderr, "invalid 'addr' in filter string.\n");
- exit(EXIT_FAILURE);
+ if (!addr)
+ {
+ fprintf(stderr, "invalid 'addr' in filter string.\n");
+ exit(EXIT_FAILURE);
+ }
+ addr_chunk = chunk_clone(addr->get_address(addr));
+ array_insert_create(to_free, ARRAY_TAIL, addr_chunk.ptr);
+ addr->destroy(addr);
}
break;
case FIL_TSTAMP:
@@ -710,11 +723,11 @@ static enumerator_t *create_lease_query(char *filter)
"AND (? OR (identities.type = ? AND identities.data = ?)) "
"AND (? OR address = ?)",
DB_INT, pool == NULL, DB_TEXT, pool,
- DB_INT, id == NULL,
- DB_INT, id ? id->get_type(id) : 0,
- DB_BLOB, id ? id->get_encoding(id) : chunk_empty,
- DB_INT, addr == NULL,
- DB_BLOB, addr ? addr->get_address(addr) : chunk_empty,
+ DB_INT, !id_chunk.ptr,
+ DB_INT, id_type,
+ DB_BLOB, id_chunk,
+ DB_INT, !addr_chunk.ptr,
+ DB_BLOB, addr_chunk,
DB_INT, tstamp == 0, DB_UINT, tstamp, DB_UINT, tstamp,
DB_INT, !valid, DB_INT, time(NULL),
DB_INT, !expired, DB_INT, time(NULL),
@@ -722,14 +735,13 @@ static enumerator_t *create_lease_query(char *filter)
/* union */
DB_INT, !(valid || expired),
DB_INT, pool == NULL, DB_TEXT, pool,
- DB_INT, id == NULL,
- DB_INT, id ? id->get_type(id) : 0,
- DB_BLOB, id ? id->get_encoding(id) : chunk_empty,
- DB_INT, addr == NULL,
- DB_BLOB, addr ? addr->get_address(addr) : chunk_empty,
+ DB_INT, !id_chunk.ptr,
+ DB_INT, id_type,
+ DB_BLOB, id_chunk,
+ DB_INT, !addr_chunk.ptr,
+ DB_BLOB, addr_chunk,
/* res */
DB_TEXT, DB_BLOB, DB_INT, DB_BLOB, DB_UINT, DB_UINT, DB_UINT);
- /* id and addr leak but we can't destroy them until query is destroyed. */
return query;
}
@@ -739,6 +751,7 @@ static enumerator_t *create_lease_query(char *filter)
static void leases(char *filter, bool utc)
{
enumerator_t *query;
+ array_t *to_free = NULL;
chunk_t address_chunk, identity_chunk;
int identity_type;
char *name;
@@ -748,7 +761,7 @@ static void leases(char *filter, bool utc)
identification_t *identity;
bool found = FALSE;
- query = create_lease_query(filter);
+ query = create_lease_query(filter, &to_free);
if (!query)
{
fprintf(stderr, "querying leases failed.\n");
@@ -809,6 +822,10 @@ static void leases(char *filter, bool utc)
identity->destroy(identity);
}
query->destroy(query);
+ if (to_free)
+ {
+ array_destroy_function(to_free, (void*)free, NULL);
+ }
if (!found)
{
fprintf(stderr, "no matching leases found.\n");