diff options
Diffstat (limited to 'src/libstrongswan')
32 files changed, 1231 insertions, 679 deletions
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index 08409d503..1423db5c3 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -50,6 +50,7 @@ utils/linked_list.c utils/linked_list.h \ utils/enumerator.c utils/enumerator.h \ utils/optionsfrom.c utils/optionsfrom.h \ utils/mutex.c utils/mutex.h \ +utils/backtrace.c utils/backtrace.h \ plugins/plugin_loader.c plugins/plugin_loader.h plugins/plugin.h libstrongswan_la_LIBADD = -lpthread -ldl @@ -63,6 +64,10 @@ if USE_LEAK_DETECTIVE libstrongswan_la_SOURCES += utils/leak_detective.c utils/leak_detective.h endif +if USE_LOCK_PROFILER + AM_CFLAGS += -DLOCK_PROFILER +endif + if USE_INTEGRITY_TEST libstrongswan_la_SOURCES += \ fips/fips_canister_end.c @@ -72,11 +77,11 @@ EXTRA_DIST = asn1/oid.txt asn1/oid.pl BUILT_SOURCES = asn1/oid.c asn1/oid.h MAINTAINERCLEANFILES = asn1/oid.c asn1/oid.h -asn1/oid.c : asn1/oid.txt asn1/oid.pl - cd asn1 && $(PERL) oid.pl +asn1/oid.c : asn1/oid.pl asn1/oid.txt + (cd `dirname $<` && $(PERL) `basename $<`) -asn1/oid.h : asn1/oid.txt asn1/oid.pl - cd asn1 && $(PERL) oid.pl +asn1/oid.h : asn1/oid.pl asn1/oid.txt + (cd `dirname $<` && $(PERL) `basename $<`) # build plugins with their own Makefile diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in index e73411aa6..f1cf4f554 100644 --- a/src/libstrongswan/Makefile.in +++ b/src/libstrongswan/Makefile.in @@ -34,26 +34,27 @@ build_triplet = @build@ host_triplet = @host@ @USE_LEAK_DETECTIVE_TRUE@am__append_1 = -DLEAK_DETECTIVE @USE_LEAK_DETECTIVE_TRUE@am__append_2 = utils/leak_detective.c utils/leak_detective.h -@USE_AES_TRUE@am__append_3 = plugins/aes -@USE_DES_TRUE@am__append_4 = plugins/des -@USE_MD5_TRUE@am__append_5 = plugins/md5 -@USE_SHA1_TRUE@am__append_6 = plugins/sha1 -@USE_SHA2_TRUE@am__append_7 = plugins/sha2 -@USE_FIPS_PRF_TRUE@am__append_8 = plugins/fips_prf -@USE_GMP_TRUE@am__append_9 = plugins/gmp -@USE_RANDOM_TRUE@am__append_10 = plugins/random -@USE_HMAC_TRUE@am__append_11 = plugins/hmac -@USE_XCBC_TRUE@am__append_12 = plugins/xcbc -@USE_X509_TRUE@am__append_13 = plugins/x509 -@USE_PUBKEY_TRUE@am__append_14 = plugins/pubkey -@USE_CURL_TRUE@am__append_15 = plugins/curl -@USE_LDAP_TRUE@am__append_16 = plugins/ldap -@USE_MYSQL_TRUE@am__append_17 = plugins/mysql -@USE_SQLITE_TRUE@am__append_18 = plugins/sqlite -@USE_PADLOCK_TRUE@am__append_19 = plugins/padlock -@USE_OPENSSL_TRUE@am__append_20 = plugins/openssl -@USE_AGENT_TRUE@am__append_21 = plugins/agent -@USE_INTEGRITY_TEST_TRUE@am__append_22 = fips +@USE_LOCK_PROFILER_TRUE@am__append_3 = -DLOCK_PROFILER +@USE_AES_TRUE@am__append_4 = plugins/aes +@USE_DES_TRUE@am__append_5 = plugins/des +@USE_MD5_TRUE@am__append_6 = plugins/md5 +@USE_SHA1_TRUE@am__append_7 = plugins/sha1 +@USE_SHA2_TRUE@am__append_8 = plugins/sha2 +@USE_FIPS_PRF_TRUE@am__append_9 = plugins/fips_prf +@USE_GMP_TRUE@am__append_10 = plugins/gmp +@USE_RANDOM_TRUE@am__append_11 = plugins/random +@USE_HMAC_TRUE@am__append_12 = plugins/hmac +@USE_XCBC_TRUE@am__append_13 = plugins/xcbc +@USE_X509_TRUE@am__append_14 = plugins/x509 +@USE_PUBKEY_TRUE@am__append_15 = plugins/pubkey +@USE_CURL_TRUE@am__append_16 = plugins/curl +@USE_LDAP_TRUE@am__append_17 = plugins/ldap +@USE_MYSQL_TRUE@am__append_18 = plugins/mysql +@USE_SQLITE_TRUE@am__append_19 = plugins/sqlite +@USE_PADLOCK_TRUE@am__append_20 = plugins/padlock +@USE_OPENSSL_TRUE@am__append_21 = plugins/openssl +@USE_AGENT_TRUE@am__append_22 = plugins/agent +@USE_INTEGRITY_TEST_TRUE@am__append_23 = fips subdir = src/libstrongswan DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -105,7 +106,8 @@ am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \ utils/iterator.h utils/lexparser.c utils/lexparser.h \ utils/linked_list.c utils/linked_list.h utils/enumerator.c \ utils/enumerator.h utils/optionsfrom.c utils/optionsfrom.h \ - utils/mutex.c utils/mutex.h plugins/plugin_loader.c \ + utils/mutex.c utils/mutex.h utils/backtrace.c \ + utils/backtrace.h plugins/plugin_loader.c \ plugins/plugin_loader.h plugins/plugin.h \ utils/leak_detective.c utils/leak_detective.h \ fips/fips_canister_start.c fips/fips.c fips/fips.h \ @@ -126,7 +128,7 @@ am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \ @USE_INTEGRITY_TEST_FALSE@ database_factory.lo utils.lo host.lo \ @USE_INTEGRITY_TEST_FALSE@ identification.lo lexparser.lo \ @USE_INTEGRITY_TEST_FALSE@ linked_list.lo enumerator.lo \ -@USE_INTEGRITY_TEST_FALSE@ optionsfrom.lo mutex.lo \ +@USE_INTEGRITY_TEST_FALSE@ optionsfrom.lo mutex.lo backtrace.lo \ @USE_INTEGRITY_TEST_FALSE@ plugin_loader.lo $(am__objects_1) @USE_INTEGRITY_TEST_TRUE@am_libstrongswan_la_OBJECTS = \ @USE_INTEGRITY_TEST_TRUE@ fips_canister_start.lo fips.lo \ @@ -144,7 +146,7 @@ am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \ @USE_INTEGRITY_TEST_TRUE@ database_factory.lo utils.lo host.lo \ @USE_INTEGRITY_TEST_TRUE@ identification.lo lexparser.lo \ @USE_INTEGRITY_TEST_TRUE@ linked_list.lo enumerator.lo \ -@USE_INTEGRITY_TEST_TRUE@ optionsfrom.lo mutex.lo \ +@USE_INTEGRITY_TEST_TRUE@ optionsfrom.lo mutex.lo backtrace.lo \ @USE_INTEGRITY_TEST_TRUE@ plugin_loader.lo $(am__objects_1) \ @USE_INTEGRITY_TEST_TRUE@ fips_canister_end.lo libstrongswan_la_OBJECTS = $(am_libstrongswan_la_OBJECTS) @@ -375,7 +377,8 @@ lib_LTLIBRARIES = libstrongswan.la @USE_INTEGRITY_TEST_FALSE@ utils/enumerator.h \ @USE_INTEGRITY_TEST_FALSE@ utils/optionsfrom.c \ @USE_INTEGRITY_TEST_FALSE@ utils/optionsfrom.h utils/mutex.c \ -@USE_INTEGRITY_TEST_FALSE@ utils/mutex.h \ +@USE_INTEGRITY_TEST_FALSE@ utils/mutex.h utils/backtrace.c \ +@USE_INTEGRITY_TEST_FALSE@ utils/backtrace.h \ @USE_INTEGRITY_TEST_FALSE@ plugins/plugin_loader.c \ @USE_INTEGRITY_TEST_FALSE@ plugins/plugin_loader.h \ @USE_INTEGRITY_TEST_FALSE@ plugins/plugin.h $(am__append_2) @@ -437,27 +440,30 @@ lib_LTLIBRARIES = libstrongswan.la @USE_INTEGRITY_TEST_TRUE@ utils/enumerator.c utils/enumerator.h \ @USE_INTEGRITY_TEST_TRUE@ utils/optionsfrom.c \ @USE_INTEGRITY_TEST_TRUE@ utils/optionsfrom.h utils/mutex.c \ -@USE_INTEGRITY_TEST_TRUE@ utils/mutex.h plugins/plugin_loader.c \ +@USE_INTEGRITY_TEST_TRUE@ utils/mutex.h utils/backtrace.c \ +@USE_INTEGRITY_TEST_TRUE@ utils/backtrace.h \ +@USE_INTEGRITY_TEST_TRUE@ plugins/plugin_loader.c \ @USE_INTEGRITY_TEST_TRUE@ plugins/plugin_loader.h \ @USE_INTEGRITY_TEST_TRUE@ plugins/plugin.h $(am__append_2) \ @USE_INTEGRITY_TEST_TRUE@ fips/fips_canister_end.c libstrongswan_la_LIBADD = -lpthread -ldl INCLUDES = -I$(top_srcdir)/src/libstrongswan AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" \ - -DIPSEC_PLUGINDIR=\"${plugindir}\" $(am__append_1) + -DIPSEC_PLUGINDIR=\"${plugindir}\" $(am__append_1) \ + $(am__append_3) EXTRA_DIST = asn1/oid.txt asn1/oid.pl BUILT_SOURCES = asn1/oid.c asn1/oid.h MAINTAINERCLEANFILES = asn1/oid.c asn1/oid.h # build plugins with their own Makefile ####################################### -SUBDIRS = . $(am__append_3) $(am__append_4) $(am__append_5) \ - $(am__append_6) $(am__append_7) $(am__append_8) \ - $(am__append_9) $(am__append_10) $(am__append_11) \ - $(am__append_12) $(am__append_13) $(am__append_14) \ - $(am__append_15) $(am__append_16) $(am__append_17) \ - $(am__append_18) $(am__append_19) $(am__append_20) \ - $(am__append_21) $(am__append_22) +SUBDIRS = . $(am__append_4) $(am__append_5) $(am__append_6) \ + $(am__append_7) $(am__append_8) $(am__append_9) \ + $(am__append_10) $(am__append_11) $(am__append_12) \ + $(am__append_13) $(am__append_14) $(am__append_15) \ + $(am__append_16) $(am__append_17) $(am__append_18) \ + $(am__append_19) $(am__append_20) $(am__append_21) \ + $(am__append_22) $(am__append_23) all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -530,6 +536,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asn1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asn1_parser.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builder.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/certificate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chunk.Plo@am__quote@ @@ -810,6 +817,13 @@ mutex.lo: utils/mutex.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mutex.lo `test -f 'utils/mutex.c' || echo '$(srcdir)/'`utils/mutex.c +backtrace.lo: utils/backtrace.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT backtrace.lo -MD -MP -MF $(DEPDIR)/backtrace.Tpo -c -o backtrace.lo `test -f 'utils/backtrace.c' || echo '$(srcdir)/'`utils/backtrace.c +@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/backtrace.Tpo $(DEPDIR)/backtrace.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utils/backtrace.c' object='backtrace.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o backtrace.lo `test -f 'utils/backtrace.c' || echo '$(srcdir)/'`utils/backtrace.c + plugin_loader.lo: plugins/plugin_loader.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT plugin_loader.lo -MD -MP -MF $(DEPDIR)/plugin_loader.Tpo -c -o plugin_loader.lo `test -f 'plugins/plugin_loader.c' || echo '$(srcdir)/'`plugins/plugin_loader.c @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/plugin_loader.Tpo $(DEPDIR)/plugin_loader.Plo @@ -1139,11 +1153,11 @@ uninstall-am: uninstall-libLTLIBRARIES uninstall-libLTLIBRARIES -asn1/oid.c : asn1/oid.txt asn1/oid.pl - cd asn1 && $(PERL) oid.pl +asn1/oid.c : asn1/oid.pl asn1/oid.txt + (cd `dirname $<` && $(PERL) `basename $<`) -asn1/oid.h : asn1/oid.txt asn1/oid.pl - cd asn1 && $(PERL) oid.pl +asn1/oid.h : asn1/oid.pl asn1/oid.txt + (cd `dirname $<` && $(PERL) `basename $<`) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/src/libstrongswan/crypto/crypters/crypter.h b/src/libstrongswan/crypto/crypters/crypter.h index aade888fa..fb06af97d 100644 --- a/src/libstrongswan/crypto/crypters/crypter.h +++ b/src/libstrongswan/crypto/crypters/crypter.h @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: crypter.h 3971 2008-05-16 13:27:21Z tobias $ + * $Id: crypter.h 4532 2008-10-30 13:21:21Z martin $ */ /** diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c index 9836ed468..dcc881f1d 100644 --- a/src/libstrongswan/crypto/crypto_factory.c +++ b/src/libstrongswan/crypto/crypto_factory.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: crypto_factory.c 4307 2008-08-28 09:24:42Z martin $ + * $Id: crypto_factory.c 4592 2008-11-05 16:21:57Z martin $ */ #include "crypto_factory.h" @@ -78,9 +78,9 @@ struct private_crypto_factory_t { linked_list_t *dhs; /** - * mutex to lock access to modules + * rwlock to lock access to modules */ - mutex_t *mutex; + rwlock_t *lock; }; /** @@ -93,7 +93,7 @@ static crypter_t* create_crypter(private_crypto_factory_t *this, entry_t *entry; crypter_t *crypter = NULL; - this->mutex->lock(this->mutex); + this->lock->read_lock(this->lock); enumerator = this->crypters->create_enumerator(this->crypters); while (enumerator->enumerate(enumerator, &entry)) { @@ -107,7 +107,7 @@ static crypter_t* create_crypter(private_crypto_factory_t *this, } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); return crypter; } @@ -121,7 +121,7 @@ static signer_t* create_signer(private_crypto_factory_t *this, entry_t *entry; signer_t *signer = NULL; - this->mutex->lock(this->mutex); + this->lock->read_lock(this->lock); enumerator = this->signers->create_enumerator(this->signers); while (enumerator->enumerate(enumerator, &entry)) { @@ -135,7 +135,7 @@ static signer_t* create_signer(private_crypto_factory_t *this, } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); return signer; } @@ -150,7 +150,7 @@ static hasher_t* create_hasher(private_crypto_factory_t *this, entry_t *entry; hasher_t *hasher = NULL; - this->mutex->lock(this->mutex); + this->lock->read_lock(this->lock); enumerator = this->hashers->create_enumerator(this->hashers); while (enumerator->enumerate(enumerator, &entry)) { @@ -164,7 +164,7 @@ static hasher_t* create_hasher(private_crypto_factory_t *this, } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); return hasher; } @@ -178,7 +178,7 @@ static prf_t* create_prf(private_crypto_factory_t *this, entry_t *entry; prf_t *prf = NULL; - this->mutex->lock(this->mutex); + this->lock->read_lock(this->lock); enumerator = this->prfs->create_enumerator(this->prfs); while (enumerator->enumerate(enumerator, &entry)) { @@ -192,7 +192,7 @@ static prf_t* create_prf(private_crypto_factory_t *this, } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); return prf; } @@ -206,7 +206,7 @@ static rng_t* create_rng(private_crypto_factory_t *this, rng_quality_t quality) u_int diff = ~0; rng_constructor_t constr = NULL; - this->mutex->lock(this->mutex); + this->lock->read_lock(this->lock); enumerator = this->rngs->create_enumerator(this->rngs); while (enumerator->enumerate(enumerator, &entry)) { /* find the best matching quality, but at least as good as requested */ @@ -221,7 +221,7 @@ static rng_t* create_rng(private_crypto_factory_t *this, rng_quality_t quality) } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); if (constr) { return constr(quality); @@ -239,7 +239,7 @@ static diffie_hellman_t* create_dh(private_crypto_factory_t *this, entry_t *entry; diffie_hellman_t *diffie_hellman = NULL; - this->mutex->lock(this->mutex); + this->lock->read_lock(this->lock); enumerator = this->dhs->create_enumerator(this->dhs); while (enumerator->enumerate(enumerator, &entry)) { @@ -253,7 +253,7 @@ static diffie_hellman_t* create_dh(private_crypto_factory_t *this, } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); return diffie_hellman; } @@ -268,9 +268,9 @@ static void add_crypter(private_crypto_factory_t *this, entry->algo = algo; entry->create_crypter = create; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); this->crypters->insert_last(this->crypters, entry); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -282,7 +282,7 @@ static void remove_crypter(private_crypto_factory_t *this, entry_t *entry; enumerator_t *enumerator; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); enumerator = this->crypters->create_enumerator(this->crypters); while (enumerator->enumerate(enumerator, &entry)) { @@ -293,7 +293,7 @@ static void remove_crypter(private_crypto_factory_t *this, } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -306,9 +306,9 @@ static void add_signer(private_crypto_factory_t *this, entry->algo = algo; entry->create_signer = create; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); this->signers->insert_last(this->signers, entry); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -320,7 +320,7 @@ static void remove_signer(private_crypto_factory_t *this, entry_t *entry; enumerator_t *enumerator; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); enumerator = this->signers->create_enumerator(this->signers); while (enumerator->enumerate(enumerator, &entry)) { @@ -331,7 +331,7 @@ static void remove_signer(private_crypto_factory_t *this, } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -344,9 +344,9 @@ static void add_hasher(private_crypto_factory_t *this, hash_algorithm_t algo, entry->algo = algo; entry->create_hasher = create; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); this->hashers->insert_last(this->hashers, entry); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -358,7 +358,7 @@ static void remove_hasher(private_crypto_factory_t *this, entry_t *entry; enumerator_t *enumerator; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); enumerator = this->hashers->create_enumerator(this->hashers); while (enumerator->enumerate(enumerator, &entry)) { @@ -369,7 +369,7 @@ static void remove_hasher(private_crypto_factory_t *this, } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -382,9 +382,9 @@ static void add_prf(private_crypto_factory_t *this, entry->algo = algo; entry->create_prf = create; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); this->prfs->insert_last(this->prfs, entry); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -395,7 +395,7 @@ static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create) entry_t *entry; enumerator_t *enumerator; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); enumerator = this->prfs->create_enumerator(this->prfs); while (enumerator->enumerate(enumerator, &entry)) { @@ -406,7 +406,7 @@ static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create) } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -419,9 +419,9 @@ static void add_rng(private_crypto_factory_t *this, rng_quality_t quality, entry->algo = quality; entry->create_rng = create; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); this->rngs->insert_last(this->rngs, entry); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -432,7 +432,7 @@ static void remove_rng(private_crypto_factory_t *this, rng_constructor_t create) entry_t *entry; enumerator_t *enumerator; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); enumerator = this->rngs->create_enumerator(this->rngs); while (enumerator->enumerate(enumerator, &entry)) { @@ -443,7 +443,7 @@ static void remove_rng(private_crypto_factory_t *this, rng_constructor_t create) } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -456,9 +456,9 @@ static void add_dh(private_crypto_factory_t *this, diffie_hellman_group_t group, entry->algo = group; entry->create_dh = create; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); this->dhs->insert_last(this->dhs, entry); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -469,7 +469,7 @@ static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create) entry_t *entry; enumerator_t *enumerator; - this->mutex->lock(this->mutex); + this->lock->write_lock(this->lock); enumerator = this->dhs->create_enumerator(this->dhs); while (enumerator->enumerate(enumerator, &entry)) { @@ -480,7 +480,7 @@ static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create) } } enumerator->destroy(enumerator); - this->mutex->unlock(this->mutex); + this->lock->unlock(this->lock); } /** @@ -511,12 +511,12 @@ static bool unique_check(linked_list_t *list, entry_t **in, entry_t **out) static enumerator_t *create_enumerator(private_crypto_factory_t *this, linked_list_t *list, void *filter) { - this->mutex->lock(this->mutex); + this->lock->read_lock(this->lock); return enumerator_create_filter( enumerator_create_filter( list->create_enumerator(list), (void*)unique_check, linked_list_create(), (void*)list->destroy), - filter, this->mutex, (void*)this->mutex->unlock); + filter, this->lock, (void*)this->lock->unlock); } /** @@ -615,7 +615,7 @@ static void destroy(private_crypto_factory_t *this) this->prfs->destroy_function(this->prfs, free); this->rngs->destroy_function(this->rngs, free); this->dhs->destroy_function(this->dhs, free); - this->mutex->destroy(this->mutex); + this->lock->destroy(this->lock); free(this); } @@ -657,7 +657,7 @@ crypto_factory_t *crypto_factory_create() this->prfs = linked_list_create(); this->rngs = linked_list_create(); this->dhs = linked_list_create(); - this->mutex = mutex_create(MUTEX_RECURSIVE); + this->lock = rwlock_create(RWLOCK_DEFAULT); return &this->public; } diff --git a/src/libstrongswan/crypto/diffie_hellman.h b/src/libstrongswan/crypto/diffie_hellman.h index c66ae56c3..ce8ab8e21 100644 --- a/src/libstrongswan/crypto/diffie_hellman.h +++ b/src/libstrongswan/crypto/diffie_hellman.h @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: diffie_hellman.h 4023 2008-05-29 06:55:03Z andreas $ + * $Id: diffie_hellman.h 4566 2008-11-04 13:12:11Z martin $ */ /** @@ -85,16 +85,6 @@ struct diffie_hellman_t { void (*set_other_public_value) (diffie_hellman_t *this, chunk_t value); /** - * Gets the public value of partner. - * - * Space for returned chunk is allocated and must be freed by the caller. - * - * @param value public value of partner is stored at this location - * @return SUCCESS, FAILED if other public value not set - */ - status_t (*get_other_public_value) (diffie_hellman_t *this, chunk_t *value); - - /** * Gets the own public value to transmit. * * Space for returned chunk is allocated and must be freed by the caller. diff --git a/src/libstrongswan/crypto/prf_plus.c b/src/libstrongswan/crypto/prf_plus.c index de7dbff84..3d37d4ef7 100644 --- a/src/libstrongswan/crypto/prf_plus.c +++ b/src/libstrongswan/crypto/prf_plus.c @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: prf_plus.c 3589 2008-03-13 14:14:44Z martin $ + * $Id: prf_plus.c 4524 2008-10-29 14:12:54Z martin $ */ #include <string.h> @@ -96,9 +96,16 @@ static void get_bytes(private_prf_plus_t *this, size_t length, u_int8_t *buffer) */ static void allocate_bytes(private_prf_plus_t *this, size_t length, chunk_t *chunk) { - chunk->ptr = malloc(length); - chunk->len = length; - this->public.get_bytes(&(this->public), length, chunk->ptr); + if (length) + { + chunk->ptr = malloc(length); + chunk->len = length; + get_bytes(this, length, chunk->ptr); + } + else + { + *chunk = chunk_empty; + } } /** diff --git a/src/libstrongswan/fetcher/fetcher_manager.c b/src/libstrongswan/fetcher/fetcher_manager.c index 517c9dfc9..5d58f224e 100644 --- a/src/libstrongswan/fetcher/fetcher_manager.c +++ b/src/libstrongswan/fetcher/fetcher_manager.c @@ -12,16 +12,14 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: fetcher_manager.c 3630 2008-03-20 11:27:55Z martin $ + * $Id: fetcher_manager.c 4591 2008-11-05 16:12:54Z martin $ */ -#define _GNU_SOURCE - #include "fetcher_manager.h" #include <debug.h> -#include <utils/linked_list.h> #include <utils/mutex.h> +#include <utils/linked_list.h> typedef struct private_fetcher_manager_t private_fetcher_manager_t; @@ -43,7 +41,7 @@ struct private_fetcher_manager_t { /** * read write lock to list */ - pthread_rwlock_t lock; + rwlock_t *lock; }; typedef struct { @@ -73,7 +71,7 @@ static status_t fetch(private_fetcher_manager_t *this, entry_t *entry; bool capable = FALSE; - pthread_rwlock_rdlock(&this->lock); + this->lock->read_lock(this->lock); enumerator = this->fetchers->create_enumerator(this->fetchers); while (enumerator->enumerate(enumerator, &entry)) { @@ -131,7 +129,7 @@ static status_t fetch(private_fetcher_manager_t *this, break; } enumerator->destroy(enumerator); - pthread_rwlock_unlock(&this->lock); + this->lock->unlock(this->lock); if (!capable) { DBG1("unable to fetch from %s, no capable fetcher found", url); @@ -150,9 +148,9 @@ static void add_fetcher(private_fetcher_manager_t *this, entry->url = strdup(url); entry->create = create; - pthread_rwlock_wrlock(&this->lock); + this->lock->write_lock(this->lock); this->fetchers->insert_last(this->fetchers, entry); - pthread_rwlock_unlock(&this->lock); + this->lock->unlock(this->lock); } /** @@ -164,7 +162,7 @@ static void remove_fetcher(private_fetcher_manager_t *this, enumerator_t *enumerator; entry_t *entry; - pthread_rwlock_wrlock(&this->lock); + this->lock->write_lock(this->lock); enumerator = this->fetchers->create_enumerator(this->fetchers); while (enumerator->enumerate(enumerator, &entry)) { @@ -175,7 +173,7 @@ static void remove_fetcher(private_fetcher_manager_t *this, } } enumerator->destroy(enumerator); - pthread_rwlock_unlock(&this->lock); + this->lock->unlock(this->lock); } /** @@ -184,7 +182,7 @@ static void remove_fetcher(private_fetcher_manager_t *this, static void destroy(private_fetcher_manager_t *this) { this->fetchers->destroy_function(this->fetchers, (void*)entry_destroy); - pthread_rwlock_destroy(&this->lock); + this->lock->destroy(this->lock); free(this); } @@ -201,7 +199,7 @@ fetcher_manager_t *fetcher_manager_create() this->public.destroy = (void(*)(fetcher_manager_t*))destroy; this->fetchers = linked_list_create(); - pthread_rwlock_init(&this->lock, NULL); + this->lock = rwlock_create(RWLOCK_DEFAULT); return &this->public; } diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c index a3b8eebf3..5e7d0839e 100644 --- a/src/libstrongswan/plugins/agent/agent_private_key.c +++ b/src/libstrongswan/plugins/agent/agent_private_key.c @@ -215,9 +215,13 @@ static bool read_key(private_agent_private_key_t *this, public_key_t *pubkey) chunk_t blob = chunk_from_buf(buf), key, type, tmp; len = htonl(1); - write(this->socket, &len, sizeof(len)); buf[0] = SSH_AGENT_ID_REQUEST; - write(this->socket, &buf, 1); + if (write(this->socket, &len, sizeof(len)) != sizeof(len) || + write(this->socket, &buf, 1) != 1) + { + DBG1("writing to ssh-agent failed"); + return FALSE; + } blob.len = read(this->socket, blob.ptr, blob.len); @@ -275,20 +279,36 @@ static bool sign(private_agent_private_key_t *this, signature_scheme_t scheme, } len = htonl(1 + sizeof(u_int32_t) * 3 + this->key.len + data.len); - write(this->socket, &len, sizeof(len)); buf[0] = SSH_AGENT_SIGN_REQUEST; - write(this->socket, &buf, 1); + if (write(this->socket, &len, sizeof(len)) != sizeof(len) || + write(this->socket, &buf, 1) != 1) + { + DBG1("writing to ssh-agent failed"); + return FALSE; + } len = htonl(this->key.len); - write(this->socket, &len, sizeof(len)); - write(this->socket, this->key.ptr, this->key.len); + if (write(this->socket, &len, sizeof(len)) != sizeof(len) || + write(this->socket, this->key.ptr, this->key.len) != this->key.len) + { + DBG1("writing to ssh-agent failed"); + return FALSE; + } len = htonl(data.len); - write(this->socket, &len, sizeof(len)); - write(this->socket, data.ptr, data.len); + if (write(this->socket, &len, sizeof(len)) != sizeof(len) || + write(this->socket, data.ptr, data.len) != data.len) + { + DBG1("writing to ssh-agent failed"); + return FALSE; + } flags = htonl(0); - write(this->socket, &flags, sizeof(flags)); + if (write(this->socket, &flags, sizeof(flags)) != sizeof(flags)) + { + DBG1("writing to ssh-agent failed"); + return FALSE; + } blob.len = read(this->socket, blob.ptr, blob.len); if (blob.len < sizeof(u_int32_t) + sizeof(u_char) || diff --git a/src/libstrongswan/plugins/curl/curl_fetcher.c b/src/libstrongswan/plugins/curl/curl_fetcher.c index 4754d569e..cd54c76a3 100644 --- a/src/libstrongswan/plugins/curl/curl_fetcher.c +++ b/src/libstrongswan/plugins/curl/curl_fetcher.c @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: curl_fetcher.c 3529 2008-03-05 15:26:24Z martin $ + * $Id: curl_fetcher.c 4632 2008-11-11 18:37:19Z martin $ */ #include <curl/curl.h> @@ -123,7 +123,7 @@ static bool set_option(private_curl_fetcher_t *this, fetcher_option_t option, .. case FETCH_REQUEST_DATA: { chunk_t data = va_arg(args, chunk_t); - curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, data.ptr); + curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, (char*)data.ptr); curl_easy_setopt(this->curl, CURLOPT_POSTFIELDSIZE, data.len); return TRUE; } diff --git a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c index 40e83fc4c..294fb722f 100644 --- a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c +++ b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c @@ -15,7 +15,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: gmp_diffie_hellman.c 4346 2008-09-17 09:02:30Z martin $ + * $Id: gmp_diffie_hellman.c 4566 2008-11-04 13:12:11Z martin $ */ #include <gmp.h> @@ -304,23 +304,28 @@ struct modulus_entry_t { size_t modulus_len; /* + * Optimum length of exponent in bytes. + */ + size_t opt_exponent_len; + + /* * Generator value. */ u_int16_t generator; }; /** - * All supported modulus values. + * All supported modulus values - optimum exponent size according to RFC 3526. */ static modulus_entry_t modulus_entries[] = { - {MODP_768_BIT, group1_modulus, sizeof(group1_modulus), 2}, - {MODP_1024_BIT, group2_modulus, sizeof(group2_modulus), 2}, - {MODP_1536_BIT, group5_modulus, sizeof(group5_modulus), 2}, - {MODP_2048_BIT, group14_modulus, sizeof(group14_modulus), 2}, - {MODP_3072_BIT, group15_modulus, sizeof(group15_modulus), 2}, - {MODP_4096_BIT, group16_modulus, sizeof(group16_modulus), 2}, - {MODP_6144_BIT, group17_modulus, sizeof(group17_modulus), 2}, - {MODP_8192_BIT, group18_modulus, sizeof(group18_modulus), 2}, + {MODP_768_BIT, group1_modulus, sizeof(group1_modulus), 32, 2}, + {MODP_1024_BIT, group2_modulus, sizeof(group2_modulus), 32, 2}, + {MODP_1536_BIT, group5_modulus, sizeof(group5_modulus), 32, 2}, + {MODP_2048_BIT, group14_modulus, sizeof(group14_modulus), 48, 2}, + {MODP_3072_BIT, group15_modulus, sizeof(group15_modulus), 48, 2}, + {MODP_4096_BIT, group16_modulus, sizeof(group16_modulus), 64, 2}, + {MODP_6144_BIT, group17_modulus, sizeof(group17_modulus), 64, 2}, + {MODP_8192_BIT, group18_modulus, sizeof(group18_modulus), 64, 2}, }; typedef struct private_gmp_diffie_hellman_t private_gmp_diffie_hellman_t; @@ -375,6 +380,11 @@ struct private_gmp_diffie_hellman_t { size_t p_len; /** + * Optimal exponent length. + */ + size_t opt_exponent_len; + + /** * True if shared secret is computed and stored in my_public_value. */ bool computed; @@ -430,25 +440,6 @@ static void set_other_public_value(private_gmp_diffie_hellman_t *this, chunk_t v } /** - * Implementation of gmp_diffie_hellman_t.get_other_public_value. - */ -static status_t get_other_public_value(private_gmp_diffie_hellman_t *this, - chunk_t *value) -{ - if (!this->computed) - { - return FAILED; - } - value->len = this->p_len; - value->ptr = mpz_export(NULL, NULL, 1, value->len, 1, 0, this->yb); - if (value->ptr == NULL) - { - return FAILED; - } - return SUCCESS; -} - -/** * Implementation of gmp_diffie_hellman_t.get_my_public_value. */ static void get_my_public_value(private_gmp_diffie_hellman_t *this,chunk_t *value) @@ -504,6 +495,7 @@ static status_t set_modulus(private_gmp_diffie_hellman_t *this) chunk.len = modulus_entries[i].modulus_len; mpz_import(this->p, chunk.len, 1, 1, 1, 0, chunk.ptr); this->p_len = chunk.len; + this->opt_exponent_len = modulus_entries[i].opt_exponent_len; mpz_set_ui(this->g, modulus_entries[i].generator); status = SUCCESS; break; @@ -534,11 +526,12 @@ gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group) private_gmp_diffie_hellman_t *this = malloc_thing(private_gmp_diffie_hellman_t); rng_t *rng; chunk_t random; + bool ansi_x9_42; + size_t exponent_len; /* public functions */ this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value; - this->public.dh.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value; this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value; this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group; this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy; @@ -567,11 +560,22 @@ gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group) destroy(this); return NULL; } - rng->allocate_bytes(rng, this->p_len, &random); + + ansi_x9_42 = lib->settings->get_int(lib->settings, + "charon.dh_exponent_ansi_x9_42", TRUE); + exponent_len = (ansi_x9_42) ? this->p_len : this->opt_exponent_len; + rng->allocate_bytes(rng, exponent_len, &random); rng->destroy(rng); + + if (ansi_x9_42) + { + /* achieve bitsof(p)-1 by setting MSB to 0 */ + *random.ptr &= 0x7F; + } mpz_import(this->xa, random.len, 1, 1, 1, 0, random.ptr); chunk_free(&random); - + DBG2("size of DH secret exponent: %u bits", mpz_sizeinbase(this->xa, 2)); + mpz_powm(this->ya, this->g, this->xa, this->p); return &this->public; diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c index 95c079b0b..7c83b3dea 100644 --- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -12,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: openssl_diffie_hellman.c 3896 2008-04-29 15:42:34Z tobias $ + * $Id: openssl_diffie_hellman.c 4639 2008-11-12 15:09:24Z martin $ */ #include <openssl/dh.h> @@ -38,23 +39,28 @@ struct modulus_entry_t { BIGNUM *(*get_prime)(BIGNUM *bn); /* + * Optimum length of exponent in bits. + */ + long opt_exponent_len; + + /* * Generator value. */ u_int16_t generator; }; /** - * All supported modulus values. + * All supported modulus values - optimum exponent size according to RFC 3526. */ static modulus_entry_t modulus_entries[] = { - {MODP_768_BIT, get_rfc2409_prime_768, 2}, - {MODP_1024_BIT, get_rfc2409_prime_1024, 2}, - {MODP_1536_BIT, get_rfc3526_prime_1536, 2}, - {MODP_2048_BIT, get_rfc3526_prime_2048, 2}, - {MODP_3072_BIT, get_rfc3526_prime_3072, 2}, - {MODP_4096_BIT, get_rfc3526_prime_4096, 2}, - {MODP_6144_BIT, get_rfc3526_prime_6144, 2}, - {MODP_8192_BIT, get_rfc3526_prime_8192, 2}, + {MODP_768_BIT, get_rfc2409_prime_768, 256, 2}, + {MODP_1024_BIT, get_rfc2409_prime_1024, 256, 2}, + {MODP_1536_BIT, get_rfc3526_prime_1536, 256, 2}, + {MODP_2048_BIT, get_rfc3526_prime_2048, 384, 2}, + {MODP_3072_BIT, get_rfc3526_prime_3072, 384, 2}, + {MODP_4096_BIT, get_rfc3526_prime_4096, 512, 2}, + {MODP_6144_BIT, get_rfc3526_prime_6144, 512, 2}, + {MODP_8192_BIT, get_rfc3526_prime_8192, 512, 2}, }; typedef struct private_openssl_diffie_hellman_t private_openssl_diffie_hellman_t; @@ -87,7 +93,7 @@ struct private_openssl_diffie_hellman_t { * Shared secret */ chunk_t shared_secret; - + /** * True if shared secret is computed */ @@ -95,68 +101,57 @@ struct private_openssl_diffie_hellman_t { }; /** - * Convert a BIGNUM to a chunk - */ -static void bn2chunk(BIGNUM *bn, chunk_t *chunk) -{ - chunk->len = BN_num_bytes(bn); - chunk->ptr = malloc(chunk->len); - BN_bn2bin(bn, chunk->ptr); -} - -/** - * Implementation of openssl_diffie_hellman_t.set_other_public_value. + * Implementation of openssl_diffie_hellman_t.get_my_public_value. */ -static void set_other_public_value(private_openssl_diffie_hellman_t *this, chunk_t value) +static void get_my_public_value(private_openssl_diffie_hellman_t *this, + chunk_t *value) { - int len; - BN_bin2bn(value.ptr, value.len, this->pub_key); - - len = DH_size(this->dh); - chunk_free(&this->shared_secret); - this->shared_secret = chunk_alloc(len); - - if (DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh) < 0) { - DBG1("DH shared secret computation failed"); - return; - } - - this->computed = TRUE; + *value = chunk_alloc(DH_size(this->dh)); + memset(value->ptr, 0, value->len); + BN_bn2bin(this->dh->pub_key, + value->ptr + value->len - BN_num_bytes(this->dh->pub_key)); } /** - * Implementation of openssl_diffie_hellman_t.get_other_public_value. + * Implementation of openssl_diffie_hellman_t.get_shared_secret. */ -static status_t get_other_public_value(private_openssl_diffie_hellman_t *this, - chunk_t *value) +static status_t get_shared_secret(private_openssl_diffie_hellman_t *this, + chunk_t *secret) { if (!this->computed) { return FAILED; } - bn2chunk(this->pub_key, value); + /* shared secret should requires a len according the DH group */ + *secret = chunk_alloc(DH_size(this->dh)); + memset(secret->ptr, 0, secret->len); + memcpy(secret->ptr + secret->len - this->shared_secret.len, + this->shared_secret.ptr, this->shared_secret.len); + return SUCCESS; } -/** - * Implementation of openssl_diffie_hellman_t.get_my_public_value. - */ -static void get_my_public_value(private_openssl_diffie_hellman_t *this,chunk_t *value) -{ - bn2chunk(this->dh->pub_key, value); -} /** - * Implementation of openssl_diffie_hellman_t.get_shared_secret. + * Implementation of openssl_diffie_hellman_t.set_other_public_value. */ -static status_t get_shared_secret(private_openssl_diffie_hellman_t *this, chunk_t *secret) +static void set_other_public_value(private_openssl_diffie_hellman_t *this, + chunk_t value) { - if (!this->computed) + int len; + + BN_bin2bn(value.ptr, value.len, this->pub_key); + chunk_clear(&this->shared_secret); + this->shared_secret.ptr = malloc(DH_size(this->dh)); + memset(this->shared_secret.ptr, 0xFF, this->shared_secret.len); + len = DH_compute_key(this->shared_secret.ptr, this->pub_key, this->dh); + if (len < 0) { - return FAILED; + DBG1("DH shared secret computation failed"); + return; } - *secret = chunk_clone(this->shared_secret); - return SUCCESS; + this->shared_secret.len = len; + this->computed = TRUE; } /** @@ -173,6 +168,11 @@ static diffie_hellman_group_t get_dh_group(private_openssl_diffie_hellman_t *thi static status_t set_modulus(private_openssl_diffie_hellman_t *this) { int i; + bool ansi_x9_42; + + ansi_x9_42 = lib->settings->get_bool(lib->settings, + "charon.dh_exponent_ansi_x9_42", TRUE); + for (i = 0; i < (sizeof(modulus_entries) / sizeof(modulus_entry_t)); i++) { if (modulus_entries[i].group == this->group) @@ -180,6 +180,10 @@ static status_t set_modulus(private_openssl_diffie_hellman_t *this) this->dh->p = modulus_entries[i].get_prime(NULL); this->dh->g = BN_new(); BN_set_word(this->dh->g, modulus_entries[i].generator); + if (!ansi_x9_42) + { + this->dh->length = modulus_entries[i].opt_exponent_len; + } return SUCCESS; } } @@ -193,7 +197,7 @@ static void destroy(private_openssl_diffie_hellman_t *this) { BN_clear_free(this->pub_key); DH_free(this->dh); - chunk_free(&this->shared_secret); + chunk_clear(&this->shared_secret); free(this); } @@ -206,7 +210,6 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t g this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value; - this->public.dh.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value; this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value; this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group; this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy; @@ -220,7 +223,6 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t g this->group = group; this->computed = FALSE; - this->pub_key = BN_new(); this->shared_secret = chunk_empty; @@ -237,6 +239,7 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(diffie_hellman_group_t g destroy(this); return NULL; } + DBG2("size of DH secret exponent: %d bits", BN_num_bits(this->dh->priv_key)); return &this->public; } diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c index 9d2bd44cd..9a89ad045 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: openssl_ec_diffie_hellman.c 4052 2008-06-10 09:19:18Z tobias $ + * $Id: openssl_ec_diffie_hellman.c 4566 2008-11-04 13:12:11Z martin $ */ #include <openssl/ec.h> @@ -217,24 +217,6 @@ static void set_other_public_value(private_openssl_ec_diffie_hellman_t *this, ch } /** - * Implementation of openssl_ec_diffie_hellman_t.get_other_public_value. - */ -static status_t get_other_public_value(private_openssl_ec_diffie_hellman_t *this, - chunk_t *value) -{ - if (!this->computed) - { - return FAILED; - } - - if (!ecp2chunk(this->ec_group, this->pub_key, value)) - { - return FAILED; - } - return SUCCESS; -} - -/** * Implementation of openssl_ec_diffie_hellman_t.get_my_public_value. */ static void get_my_public_value(private_openssl_ec_diffie_hellman_t *this,chunk_t *value) @@ -283,7 +265,6 @@ openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(diffie_hellman_gro this->public.dh.get_shared_secret = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_shared_secret; this->public.dh.set_other_public_value = (void (*)(diffie_hellman_t *, chunk_t )) set_other_public_value; - this->public.dh.get_other_public_value = (status_t (*)(diffie_hellman_t *, chunk_t *)) get_other_public_value; this->public.dh.get_my_public_value = (void (*)(diffie_hellman_t *, chunk_t *)) get_my_public_value; this->public.dh.get_dh_group = (diffie_hellman_group_t (*)(diffie_hellman_t *)) get_dh_group; this->public.dh.destroy = (void (*)(diffie_hellman_t *)) destroy; diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index 82c54a95e..dcc78aed6 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -12,15 +13,18 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: openssl_plugin.c 4309 2008-08-28 11:07:57Z martin $ + * $Id: openssl_plugin.c 4583 2008-11-05 12:37:37Z martin $ */ #include <openssl/evp.h> #include <openssl/engine.h> +#include <openssl/crypto.h> +#include <pthread.h> #include "openssl_plugin.h" #include <library.h> +#include <utils/mutex.h> #include "openssl_crypter.h" #include "openssl_hasher.h" #include "openssl_diffie_hellman.h" @@ -44,6 +48,120 @@ struct private_openssl_plugin_t { }; /** + * Array of static mutexs, with CRYPTO_num_locks() mutex + */ +static mutex_t **mutex = NULL; + +/** + * Locking callback for static locks + */ +static void locking_function(int mode, int type, const char *file, int line) +{ + if (mutex) + { + if (mode & CRYPTO_LOCK) + { + mutex[type]->lock(mutex[type]); + } + else + { + mutex[type]->unlock(mutex[type]); + } + } +} + +/** + * Implementation of dynlock + */ +struct CRYPTO_dynlock_value { + mutex_t *mutex; +}; + +/** + * Callback to create a dynamic lock + */ +static struct CRYPTO_dynlock_value *create_function(const char *file, int line) +{ + struct CRYPTO_dynlock_value *lock; + + lock = malloc_thing(struct CRYPTO_dynlock_value); + lock->mutex = mutex_create(MUTEX_DEFAULT); + return lock; +} + +/** + * Callback to (un-)lock a dynamic lock + */ +static void lock_function(int mode, struct CRYPTO_dynlock_value *lock, + const char *file, int line) +{ + if (mode & CRYPTO_LOCK) + { + lock->mutex->lock(lock->mutex); + } + else + { + lock->mutex->unlock(lock->mutex); + } +} + +/** + * Callback to destroy a dynamic lock + */ +static void destroy_function(struct CRYPTO_dynlock_value *lock, + const char *file, int line) +{ + lock->mutex->destroy(lock->mutex); + free(lock); +} + +/** + * Thread-ID callback function + */ +static unsigned long id_function(void) +{ + return pthread_self(); +} + +/** + * initialize OpenSSL for multi-threaded use + */ +static void threading_init() +{ + int i, num_locks; + + CRYPTO_set_id_callback(id_function); + CRYPTO_set_locking_callback(locking_function); + + CRYPTO_set_dynlock_create_callback(create_function); + CRYPTO_set_dynlock_lock_callback(lock_function); + CRYPTO_set_dynlock_destroy_callback(destroy_function); + + num_locks = CRYPTO_num_locks(); + mutex = malloc(sizeof(mutex_t*) * num_locks); + for (i = 0; i < num_locks; i++) + { + mutex[i] = mutex_create(MUTEX_DEFAULT); + } +} + +/** + * cleanup OpenSSL threading locks + */ +static void threading_cleanup() +{ + int i, num_locks; + + num_locks = CRYPTO_num_locks(); + for (i = 0; i < num_locks; i++) + { + mutex[i]->destroy(mutex[i]); + } + free(mutex); + mutex = NULL; +} + +/** * Implementation of openssl_plugin_t.destroy */ static void destroy(private_openssl_plugin_t *this) @@ -68,6 +186,8 @@ static void destroy(private_openssl_plugin_t *this) ENGINE_cleanup(); EVP_cleanup(); + threading_cleanup(); + free(this); } @@ -80,6 +200,8 @@ plugin_t *plugin_create() this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + threading_init(); + OpenSSL_add_all_algorithms(); /* activate support for hardware accelerators */ diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index 8ad75215a..a815ce622 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: openssl_rsa_private_key.c 4317 2008-09-02 11:00:13Z martin $ + * $Id: openssl_rsa_private_key.c 4564 2008-11-04 13:01:36Z martin $ */ #include "openssl_rsa_private_key.h" @@ -74,9 +74,11 @@ openssl_rsa_public_key_t *openssl_rsa_public_key_create_from_n_e(BIGNUM *n, BIGN * Build an EMPSA PKCS1 signature described in PKCS#1 */ static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this, - int type, chunk_t data, chunk_t *signature) + int type, chunk_t data, chunk_t *out) { bool success = FALSE; + u_char *sig = NULL; + u_int len; const EVP_MD *hasher = EVP_get_digestbynid(type); if (!hasher) { @@ -105,14 +107,17 @@ static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this, goto error; } - *signature = chunk_alloc(RSA_size(this->rsa)); - - if (!EVP_SignFinal(ctx, signature->ptr, &signature->len, key)) + sig = malloc(EVP_PKEY_size(key)); + if (EVP_SignFinal(ctx, sig, &len, key)) { - goto error; + out->ptr = sig; + out->len = len; + success = TRUE; + } + else + { + free(sig); } - - success = TRUE; error: if (key) diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index 61b5b9b64..794fa8123 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: openssl_rsa_public_key.c 4317 2008-09-02 11:00:13Z martin $ + * $Id: openssl_rsa_public_key.c 4567 2008-11-04 14:05:42Z martin $ */ #include "openssl_rsa_public_key.h" @@ -90,13 +90,11 @@ static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this, goto error; } - /* remove any preceding 0-bytes from signature */ - while (signature.len && *(signature.ptr) == 0x00) + /* VerifyFinal expects a signature of exactly RSA size (no leading 0x00) */ + if (signature.len > RSA_size(this->rsa)) { - signature.len -= 1; - signature.ptr++; + signature = chunk_skip(signature, signature.len - RSA_size(this->rsa)); } - valid = (EVP_VerifyFinal(ctx, signature.ptr, signature.len, key) == 1); error: diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c index caae5e08d..257a903e4 100644 --- a/src/libstrongswan/plugins/x509/x509_ac.c +++ b/src/libstrongswan/plugins/x509/x509_ac.c @@ -21,6 +21,8 @@ #include "x509_ac.h" #include "ietf_attr_list.h" +#include <time.h> + #include <library.h> #include <debug.h> #include <asn1/oid.h> diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index c82d14a17..9f76c3486 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -17,7 +17,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: x509_cert.c 4317 2008-09-02 11:00:13Z martin $ + * $Id: x509_cert.c 4576 2008-11-05 08:32:38Z martin $ */ #define _GNU_SOURCE @@ -25,6 +25,7 @@ #include "x509_cert.h" #include <sys/stat.h> +#include <time.h> #include <unistd.h> #include <string.h> #include <stdio.h> diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c index eb9bfe903..8375d88ef 100644 --- a/src/libstrongswan/plugins/x509/x509_crl.c +++ b/src/libstrongswan/plugins/x509/x509_crl.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: x509_crl.c 4317 2008-09-02 11:00:13Z martin $ + * $Id: x509_crl.c 4576 2008-11-05 08:32:38Z martin $ */ #include "x509_crl.h" @@ -20,6 +20,8 @@ typedef struct private_x509_crl_t private_x509_crl_t; typedef struct revoked_t revoked_t; +#include <time.h> + #include <debug.h> #include <library.h> #include <asn1/oid.h> diff --git a/src/libstrongswan/settings.c b/src/libstrongswan/settings.c index 6f9e40395..a02823ba0 100644 --- a/src/libstrongswan/settings.c +++ b/src/libstrongswan/settings.c @@ -88,9 +88,50 @@ struct kv_t { char *value; }; -static char *find(section_t *section, char *key) +/** + * find a section by a given key + */ +static section_t *find_section(section_t *section, char *key, va_list args) +{ + char name[512], *pos; + enumerator_t *enumerator; + section_t *current, *found = NULL; + + if (section == NULL) + { + return NULL; + } + if (vsnprintf(name, sizeof(name), key, args) >= sizeof(name)) + { + return NULL; + } + + pos = strchr(name, '.'); + if (pos) + { + *pos = '\0'; + pos++; + } + enumerator = section->sections->create_enumerator(section->sections); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (streq(current->name, name)) + { + found = current; + break; + } + } + enumerator->destroy(enumerator); + if (found && pos) + { + return find_section(found, pos, args); + } + return found; +} + +static char *find_value(section_t *section, char *key, va_list args) { - char *name, *pos, *value = NULL; + char name[512], *pos, *value = NULL; enumerator_t *enumerator; kv_t *kv; section_t *current, *found = NULL; @@ -100,7 +141,10 @@ static char *find(section_t *section, char *key) return NULL; } - name = strdupa(key); + if (vsnprintf(name, sizeof(name), key, args) >= sizeof(name)) + { + return NULL; + } pos = strchr(name, '.'); if (pos) @@ -119,7 +163,7 @@ static char *find(section_t *section, char *key) enumerator->destroy(enumerator); if (found) { - return find(found, pos); + return find_value(found, pos, args); } } else @@ -141,11 +185,14 @@ static char *find(section_t *section, char *key) /** * Implementation of settings_t.get. */ -static char* get_str(private_settings_t *this, char *key, char *def) +static char* get_str(private_settings_t *this, char *key, char *def, ...) { char *value; + va_list args; - value = find(this->top, key); + va_start(args, def); + value = find_value(this->top, key, args); + va_end(args); if (value) { return value; @@ -156,11 +203,14 @@ static char* get_str(private_settings_t *this, char *key, char *def) /** * Implementation of settings_t.get_bool. */ -static bool get_bool(private_settings_t *this, char *key, bool def) +static bool get_bool(private_settings_t *this, char *key, bool def, ...) { char *value; + va_list args; - value = find(this->top, key); + va_start(args, def); + value = find_value(this->top, key, args); + va_end(args); if (value) { if (strcasecmp(value, "true") == 0 || @@ -184,12 +234,15 @@ static bool get_bool(private_settings_t *this, char *key, bool def) /** * Implementation of settings_t.get_int. */ -static int get_int(private_settings_t *this, char *key, int def) +static int get_int(private_settings_t *this, char *key, int def, ...) { char *value; int intval; + va_list args; - value = find(this->top, key); + va_start(args, def); + value = find_value(this->top, key, args); + va_end(args); if (value) { errno = 0; @@ -205,12 +258,15 @@ static int get_int(private_settings_t *this, char *key, int def) /** * Implementation of settings_t.get_time. */ -static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def) +static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def, ...) { char *value, *endptr; u_int32_t timeval; + va_list args; - value = find(this->top, key); + va_start(args, def); + value = find_value(this->top, key, args); + va_end(args); if (value) { errno = 0; @@ -239,6 +295,37 @@ static u_int32_t get_time(private_settings_t *this, char *key, u_int32_t def) } /** + * Enumerate section names, not sections + */ +static bool section_filter(void *null, section_t **in, char **out) +{ + *out = (*in)->name; + return TRUE; +} + +/** + * Implementation of settings_t.create_section_enumerator + */ +static enumerator_t* create_section_enumerator(private_settings_t *this, + char *key, ...) +{ + section_t *section; + va_list args; + + va_start(args, key); + section = find_section(this->top, key, args); + va_end(args); + + if (!section) + { + return enumerator_create_empty(); + } + return enumerator_create_filter( + section->sections->create_enumerator(section->sections), + (void*)section_filter, NULL, NULL); +} + +/** * destroy a section */ static void section_destroy(section_t *this) @@ -400,10 +487,11 @@ settings_t *settings_create(char *file) { private_settings_t *this = malloc_thing(private_settings_t); - this->public.get_str = (char*(*)(settings_t*, char *key, char* def))get_str; - this->public.get_int = (int(*)(settings_t*, char *key, int def))get_int; - this->public.get_time = (u_int32_t(*)(settings_t*, char *key, u_int32_t def))get_time; - this->public.get_bool = (bool(*)(settings_t*, char *key, bool def))get_bool; + this->public.get_str = (char*(*)(settings_t*, char *key, char* def, ...))get_str; + this->public.get_int = (int(*)(settings_t*, char *key, int def, ...))get_int; + this->public.get_time = (u_int32_t(*)(settings_t*, char *key, u_int32_t def, ...))get_time; + this->public.get_bool = (bool(*)(settings_t*, char *key, bool def, ...))get_bool; + this->public.create_section_enumerator = (enumerator_t*(*)(settings_t*,char *section, ...))create_section_enumerator; this->public.destroy = (void(*)(settings_t*))destroy; this->top = NULL; diff --git a/src/libstrongswan/settings.h b/src/libstrongswan/settings.h index 451c2a583..0f41878c5 100644 --- a/src/libstrongswan/settings.h +++ b/src/libstrongswan/settings.h @@ -26,11 +26,12 @@ typedef struct settings_t settings_t; #include <library.h> +#include <utils/enumerator.h> /** * Generic configuration options read from a config file. * - * The sytax is quite simple: + * The syntax is quite simple: * * settings := (section|keyvalue)* * section := name { settings } @@ -38,8 +39,8 @@ typedef struct settings_t settings_t; * * E.g.: * @code - a = b - section-one { + a = b + section-one { somevalue = asdf subsection { othervalue = xxx @@ -58,43 +59,56 @@ struct settings_t { /** * Get a settings value as a string. * - * @param key key including sections + * @param key key including sections, printf style format * @param def value returned if key not found + * @param ... argument list for key * @return value pointing to internal string */ - char* (*get_str)(settings_t *this, char *key, char *def); + char* (*get_str)(settings_t *this, char *key, char *def, ...); /** * Get a boolean yes|no, true|false value. * - * @param jey key including sections - * @param def default value returned if key not found + * @param key key including sections, printf style format + * @param def value returned if key not found + * @param ... argument list for key * @return value of the key */ - bool (*get_bool)(settings_t *this, char *key, bool def); + bool (*get_bool)(settings_t *this, char *key, bool def, ...); /** * Get an integer value. * - * @param key key including sections - * @param def default value to return if key not found + * @param key key including sections, printf style format + * @param def value returned if key not found + * @param ... argument list for key * @return value of the key */ - int (*get_int)(settings_t *this, char *key, int def); + int (*get_int)(settings_t *this, char *key, int def, ...); /** * Get a time value. * - * @param key key including sections - * @param def default value to return if key not found + * @param key key including sections, printf style format + * @param def value returned if key not found + * @param ... argument list for key * @return value of the key */ - u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def); - + u_int32_t (*get_time)(settings_t *this, char *key, u_int32_t def, ...); + /** - * Destroy a settings instance. - */ - void (*destroy)(settings_t *this); + * Create an enumerator over subsection names of a section. + * + * @param section section including parents, printf style format + * @param ... argument list for key + * @return enumerator over subsection names + */ + enumerator_t* (*create_section_enumerator)(settings_t *this, + char *section, ...); + /** + * Destroy a settings instance. + */ + void (*destroy)(settings_t *this); }; /** diff --git a/src/libstrongswan/utils.h b/src/libstrongswan/utils.h index 4af7df9ad..a5900201a 100644 --- a/src/libstrongswan/utils.h +++ b/src/libstrongswan/utils.h @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: utils.h 4305 2008-08-28 07:47:55Z tobias $ + * $Id: utils.h 4632 2008-11-11 18:37:19Z martin $ */ /** @@ -96,6 +96,11 @@ #define countof(array) (sizeof(array)/sizeof(array[0])) /** + * Ignore result of functions tagged with warn_unused_result attributes + */ +#define ignore_result(call) { if(call); } + +/** * Assign a function as a class method */ #define ASSIGN(method, function) (method = (typeof(method))function) diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c new file mode 100644 index 000000000..3caafdc38 --- /dev/null +++ b/src/libstrongswan/utils/backtrace.c @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2006-2008 Martin Willi + * 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. + * + * $Id$ + */ + +#define _GNU_SOURCE + +#ifdef HAVE_DLADDR +# include <dlfcn.h> +#endif /* HAVE_DLADDR */ + +#ifdef HAVE_BACKTRACE +# include <execinfo.h> +#endif /* HAVE_BACKTRACE */ + +#include "backtrace.h" + +typedef struct private_backtrace_t private_backtrace_t; + +/** + * Private data of an backtrace_t object. + */ +struct private_backtrace_t { + + /** + * Public backtrace_t interface. + */ + backtrace_t public; + + /** + * Number of stacks frames obtained in stack_frames + */ + int frame_count; + + /** + * Recorded stack frames. + */ + void *frames[]; +}; + +/** + * Implementation of backtrace_t.log + */ +static void log_(private_backtrace_t *this, FILE *file) +{ +#ifdef HAVE_BACKTRACE + size_t i; + char **strings; + + strings = backtrace_symbols(this->frames, this->frame_count); + + fprintf(file, " dumping %d stack frame addresses:\n", this->frame_count); + for (i = 0; i < this->frame_count; i++) + { +#ifdef HAVE_DLADDR + Dl_info info; + + if (dladdr(this->frames[i], &info)) + { + char cmd[1024]; + FILE *output; + char c; + void *ptr = this->frames[i]; + + if (strstr(info.dli_fname, ".so")) + { + ptr = (void*)(this->frames[i] - info.dli_fbase); + } + snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", info.dli_fname, ptr); + if (info.dli_sname) + { + fprintf(file, " \e[33m%s\e[0m @ %p (\e[31m%s\e[0m+0x%x) [%p]\n", + info.dli_fname, info.dli_fbase, info.dli_sname, + this->frames[i] - info.dli_saddr, this->frames[i]); + } + else + { + fprintf(file, " \e[33m%s\e[0m @ %p [%p]\n", info.dli_fname, + info.dli_fbase, this->frames[i]); + } + fprintf(file, " -> \e[32m"); + output = popen(cmd, "r"); + if (output) + { + while (TRUE) + { + c = getc(output); + if (c == '\n' || c == EOF) + { + break; + } + fputc(c, file); + } + pclose(output); + } + else + { +#endif /* HAVE_DLADDR */ + fprintf(file, " %s\n", strings[i]); +#ifdef HAVE_DLADDR + } + fprintf(file, "\n\e[0m"); + } + else + { + fprintf(file, " %s\n", strings[i]); + } +#endif /* HAVE_DLADDR */ + } + free (strings); +#else /* !HAVE_BACKTRACE */ + fprintf(file, "C library does not support backtrace().\n"); +#endif /* HAVE_BACKTRACE */ +} + +/** + * Implementation of backtrace_t.contains_function + */ +static bool contains_function(private_backtrace_t *this, char *function) +{ +#ifdef HAVE_DLADDR + int i; + + for (i = 0; i< this->frame_count; i++) + { + Dl_info info; + + if (dladdr(this->frames[i], &info) && info.dli_sname) + { + if (streq(info.dli_sname, function)) + { + return TRUE; + } + } + } +#endif /* HAVE_DLADDR */ + return FALSE; +} + +/** + * Implementation of backtrace_t.destroy. + */ +static void destroy(private_backtrace_t *this) +{ + free(this); +} + +/** + * See header + */ +backtrace_t *backtrace_create(int skip) +{ + private_backtrace_t *this; + void *frames[50]; + int frame_count = 0; + +#ifdef HAVE_BACKTRACE + frame_count = backtrace(frames, countof(frames)); +#endif /* HAVE_BACKTRACE */ + frame_count = max(frame_count - skip, 0); + this = malloc(sizeof(private_backtrace_t) + frame_count * sizeof(void*)); + memcpy(this->frames, frames + skip, frame_count * sizeof(void*)); + this->frame_count = frame_count; + + this->public.log = (void(*)(backtrace_t*,FILE*))log_; + this->public.contains_function = (bool(*)(backtrace_t*, char *function))contains_function; + this->public.destroy = (void(*)(backtrace_t*))destroy; + + return &this->public; +} + diff --git a/src/libstrongswan/utils/backtrace.h b/src/libstrongswan/utils/backtrace.h new file mode 100644 index 000000000..72effd01e --- /dev/null +++ b/src/libstrongswan/utils/backtrace.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008 Martin Willi + * 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. + */ + +/** + * @defgroup backtrace backtrace + * @{ @ingroup utils + */ + +#ifndef BACKTRACE_H_ +#define BACKTRACE_H_ + +#include <stdio.h> + +#include <library.h> + +typedef struct backtrace_t backtrace_t; + +/** + * A backtrace registers the frames on the stack during creation. + */ +struct backtrace_t { + + /** + * Log the backtrace to a FILE stream. + */ + void (*log)(backtrace_t *this, FILE *file); + + /** + * Check if the backtrace contains a frame in a specific function. + * + * @param function name + * @return TRUE if function is in the stack + */ + bool (*contains_function)(backtrace_t *this, char *function); + + /** + * Destroy a backtrace instance. + */ + void (*destroy)(backtrace_t *this); +}; + +/** + * Create a backtrace of the current stack. + * + * @param skip how many of the innerst frames to skip + * @return backtrace + */ +backtrace_t *backtrace_create(int skip); + +#endif /* BACKTRACE_H_ @}*/ + diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c index eb87f27bc..4702222e8 100644 --- a/src/libstrongswan/utils/host.c +++ b/src/libstrongswan/utils/host.c @@ -15,7 +15,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: host.c 4056 2008-06-11 07:44:23Z martin $ + * $Id: host.c 4639 2008-11-12 15:09:24Z martin $ */ #define _GNU_SOURCE @@ -27,6 +27,9 @@ #include <debug.h> +#define IPV4_LEN 4 +#define IPV6_LEN 16 + typedef struct private_host_t private_host_t; /** @@ -83,17 +86,17 @@ static bool is_anyaddr(private_host_t *this) { case AF_INET: { - u_int8_t default_route[4]; - memset(default_route, 0, sizeof(default_route)); - return memeq(default_route, &(this->address4.sin_addr.s_addr), - sizeof(default_route)); + u_int8_t zeroes[IPV4_LEN]; + + memset(zeroes, 0, IPV4_LEN); + return memeq(zeroes, &(this->address4.sin_addr.s_addr), IPV4_LEN); } case AF_INET6: { - u_int8_t default_route[16]; - memset(default_route, 0, sizeof(default_route)); - return memeq(default_route, &(this->address6.sin6_addr.s6_addr), - sizeof(default_route)); + u_int8_t zeroes[IPV6_LEN]; + + memset(zeroes, 0, IPV6_LEN); + return memeq(zeroes, &(this->address6.sin6_addr.s6_addr), IPV6_LEN); } default: { @@ -196,13 +199,13 @@ static chunk_t get_address(private_host_t *this) case AF_INET: { address.ptr = (char*)&(this->address4.sin_addr.s_addr); - address.len = 4; + address.len = IPV4_LEN; return address; } case AF_INET6: { address.ptr = (char*)&(this->address6.sin6_addr.s6_addr); - address.len = 16; + address.len = IPV6_LEN; return address; } default: @@ -285,33 +288,21 @@ static bool ip_equals(private_host_t *this, private_host_t *other) { if (this->address.sa_family != other->address.sa_family) { - /* 0.0.0.0 and ::0 are equal */ - if (is_anyaddr(this) && is_anyaddr(other)) - { - return TRUE; - } - - return FALSE; + /* 0.0.0.0 and 0::0 are equal */ + return (is_anyaddr(this) && is_anyaddr(other)); } switch (this->address.sa_family) { case AF_INET: { - if (memeq(&this->address4.sin_addr, &other->address4.sin_addr, - sizeof(this->address4.sin_addr))) - { - return TRUE; - } - break; + return memeq(&this->address4.sin_addr, &other->address4.sin_addr, + sizeof(this->address4.sin_addr)); } case AF_INET6: { - if (memeq(&this->address6.sin6_addr, &other->address6.sin6_addr, - sizeof(this->address6.sin6_addr))) - { - return TRUE; - } + return memeq(&this->address6.sin6_addr, &other->address6.sin6_addr, + sizeof(this->address6.sin6_addr)); } default: break; @@ -340,7 +331,7 @@ static host_diff_t get_differences(host_t *this, host_t *other) } /** - * Impelements host_t.equals + * Implements host_t.equals */ static bool equals(private_host_t *this, private_host_t *other) { @@ -353,19 +344,11 @@ static bool equals(private_host_t *this, private_host_t *other) { case AF_INET: { - if (this->address4.sin_port == other->address4.sin_port) - { - return TRUE; - } - break; + return (this->address4.sin_port == other->address4.sin_port); } case AF_INET6: { - if (this->address6.sin6_port == other->address6.sin6_port) - { - return TRUE; - } - break; + return (this->address6.sin6_port == other->address6.sin6_port); } default: break; @@ -409,8 +392,14 @@ static private_host_t *host_create_empty(void) */ host_t *host_create_from_string(char *string, u_int16_t port) { - private_host_t *this = host_create_empty(); + private_host_t *this; + if (streq(string, "%any")) + { + return host_create_any(AF_INET); + } + + this = host_create_empty(); if (strchr(string, '.')) { this->address.sa_family = AF_INET; @@ -419,7 +408,6 @@ host_t *host_create_from_string(char *string, u_int16_t port) { this->address.sa_family = AF_INET6; } - switch (this->address.sa_family) { case AF_INET: @@ -460,9 +448,14 @@ host_t *host_create_from_dns(char *string, int af, u_int16_t port) struct hostent host, *ptr; char buf[512]; int err, ret; - - if (strchr(string, ':')) - { /* gethostbyname does not like IPv6 addresses, fallback */ + + if (streq(string, "%any")) + { + return host_create_any(af ? af : AF_INET); + } + else if (strchr(string, ':')) + { + /* gethostbyname does not like IPv6 addresses - fallback */ return host_create_from_string(string, port); } @@ -511,38 +504,56 @@ host_t *host_create_from_dns(char *string, int af, u_int16_t port) */ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port) { - private_host_t *this = host_create_empty(); + private_host_t *this; - this->address.sa_family = family; switch (family) { case AF_INET: - { - if (address.len != 4) + if (address.len < IPV4_LEN) { - break; + return NULL; } - memcpy(&(this->address4.sin_addr.s_addr), address.ptr,4); - this->address4.sin_port = htons(port); - this->socklen = sizeof(struct sockaddr_in); - return &(this->public); - } + address.len = IPV4_LEN; + break; case AF_INET6: - { - if (address.len != 16) + if (address.len < IPV6_LEN) { - break; + return NULL; + } + address.len = IPV6_LEN; + break; + case AF_UNSPEC: + switch (address.len) + { + case IPV4_LEN: + family = AF_INET; + break; + case IPV6_LEN: + family = AF_INET6; + break; + default: + return NULL; } - memcpy(&(this->address6.sin6_addr.s6_addr), address.ptr, 16); + break; + default: + return NULL; + } + this = host_create_empty(); + this->address.sa_family = family; + switch (family) + { + case AF_INET: + memcpy(&this->address4.sin_addr.s_addr, address.ptr, address.len); + this->address4.sin_port = htons(port); + this->socklen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + memcpy(&this->address6.sin6_addr.s6_addr, address.ptr, address.len); this->address6.sin6_port = htons(port); this->socklen = sizeof(struct sockaddr_in6); - return &this->public; - } - default: break; } - free(this); - return NULL; + return &this->public; } /* diff --git a/src/libstrongswan/utils/host.h b/src/libstrongswan/utils/host.h index 6a1d824c6..667cc6bcc 100644 --- a/src/libstrongswan/utils/host.h +++ b/src/libstrongswan/utils/host.h @@ -170,10 +170,12 @@ host_t *host_create_from_string(char *string, u_int16_t port); host_t *host_create_from_dns(char *string, int family, u_int16_t port); /** - * Constructor to create a host_t object from an address chunk + * Constructor to create a host_t object from an address chunk. + * + * If family is AF_UNSPEC, it is guessed using address.len. * * @param family Address family, such as AF_INET or AF_INET6 - * @param address address as chunk_t in networ order + * @param address address as chunk_t in network order * @param port port number * @return host_t, NULL if family not supported/chunk invalid */ diff --git a/src/libstrongswan/utils/iterator.h b/src/libstrongswan/utils/iterator.h index a1bdad1d6..28ee74cd6 100644 --- a/src/libstrongswan/utils/iterator.h +++ b/src/libstrongswan/utils/iterator.h @@ -13,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: iterator.h 3589 2008-03-13 14:14:44Z martin $ + * $Id: iterator.h 4577 2008-11-05 08:37:09Z martin $ */ /** @@ -26,43 +26,6 @@ #include <library.h> -typedef enum hook_result_t hook_result_t; - -/** - * Return value of an iterator hook. - * - * Returning HOOK_AGAIN is useful to "inject" additional elements in an - * iteration, HOOK_NEXT is the normal iterator behavior, and HOOK_SKIP may - * be used to filter elements out. - */ -enum hook_result_t { - - /** - * A value was placed in out, hook is called again with the same "in" - */ - HOOK_AGAIN, - - /** - * A value was placed in out, hook is called again with next "in" (if any) - */ - HOOK_NEXT, - - /** - * No value in out, call again with next "in" (if any) - */ - HOOK_SKIP, -}; - -/** - * Iterator hook function prototype. - * - * @param param user supplied parameter - * @param in the value the hook receives from the iterator - * @param out the value supplied as a result to the iterator - * @return a hook_result_t - */ -typedef hook_result_t (iterator_hook_t)(void *param, void *in, void **out); - typedef struct iterator_t iterator_t; @@ -94,24 +57,6 @@ struct iterator_t { bool (*iterate) (iterator_t *this, void** value); /** - * Hook a function into the iterator. - * - * Sometimes it is useful to hook in an iterator. The hook function is - * called before any successful return of iterate(). It takes the - * iterator value, may manipulate it (or the references object), and returns - * the value that the iterate() function returns. Depending on the hook - * return value, the hook is called again, called with next, or skipped. - * A value of NULL deactivates the iterator hook. - * If an iterator is hooked, only the iterate() method is valid, - * all other methods behave undefined. - * - * @param hook iterator hook which manipulates the iterated value - * @param param user supplied parameter to pass back to the hook - */ - void (*set_iterator_hook) (iterator_t *this, iterator_hook_t *hook, - void *param); - - /** * Inserts a new item before the given iterator position. * * The iterator position is not changed after inserting diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index bc7f56ebd..73409158d 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -12,13 +12,8 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: leak_detective.c 4311 2008-08-28 16:27:48Z martin $ + * $Id: leak_detective.c 4609 2008-11-10 16:44:27Z martin $ */ - -#ifdef HAVE_DLADDR -# define _GNU_SOURCE -# include <dlfcn.h> -#endif /* HAVE_DLADDR */ #include <stddef.h> #include <string.h> @@ -28,21 +23,18 @@ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> -#include <dlfcn.h> #include <unistd.h> #include <syslog.h> #include <pthread.h> #include <netdb.h> #include <printf.h> #include <locale.h> -#ifdef HAVE_BACKTRACE -# include <execinfo.h> -#endif /* HAVE_BACKTRACE */ #include "leak_detective.h" #include <library.h> #include <debug.h> +#include <utils/backtrace.h> typedef struct private_leak_detective_t private_leak_detective_t; @@ -106,16 +98,6 @@ struct memory_header_t { u_int bytes; /** - * Stack frames at the time of allocation - */ - void *stack_frames[STACK_FRAMES_COUNT]; - - /** - * Number of stacks frames obtained in stack_frames - */ - int stack_frame_count; - - /** * Pointer to previous entry in linked list */ memory_header_t *previous; @@ -126,6 +108,11 @@ struct memory_header_t { memory_header_t *next; /** + * backtrace taken during (re-)allocation + */ + backtrace_t *backtrace; + + /** * magic bytes to detect bad free or heap underflow, MEMORY_HEADER_MAGIC */ u_int32_t magic; @@ -151,7 +138,7 @@ struct memory_tail_t { static memory_header_t first_header = { magic: MEMORY_HEADER_MAGIC, bytes: 0, - stack_frame_count: 0, + backtrace: NULL, previous: NULL, next: NULL }; @@ -162,88 +149,21 @@ static memory_header_t first_header = { static bool installed = FALSE; /** - * log stack frames queried by backtrace() - * TODO: Dump symbols of static functions. This could be done with - * the addr2line utility or the GNU BFD Library... - */ -static void log_stack_frames(void **stack_frames, int stack_frame_count) -{ -#ifdef HAVE_BACKTRACE - size_t i; - char **strings; - - strings = backtrace_symbols(stack_frames, stack_frame_count); - - fprintf(stderr, " dumping %d stack frame addresses:\n", stack_frame_count); - for (i = 0; i < stack_frame_count; i++) - { -#ifdef HAVE_DLADDR - Dl_info info; - - if (dladdr(stack_frames[i], &info)) - { - char cmd[1024]; - FILE *output; - char c; - void *ptr = stack_frames[i]; - - if (strstr(info.dli_fname, ".so")) - { - ptr = (void*)(stack_frames[i] - info.dli_fbase); - } - snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", info.dli_fname, ptr); - if (info.dli_sname) - { - fprintf(stderr, " \e[33m%s\e[0m @ %p (\e[31m%s\e[0m+0x%x) [%p]\n", - info.dli_fname, info.dli_fbase, info.dli_sname, - stack_frames[i] - info.dli_saddr, stack_frames[i]); - } - else - { - fprintf(stderr, " \e[33m%s\e[0m @ %p [%p]\n", info.dli_fname, - info.dli_fbase, stack_frames[i]); - } - fprintf(stderr, " -> \e[32m"); - output = popen(cmd, "r"); - if (output) - { - while (TRUE) - { - c = getc(output); - if (c == '\n' || c == EOF) - { - break; - } - fputc(c, stderr); - } - } - else - { -#endif /* HAVE_DLADDR */ - fprintf(stderr, " %s\n", strings[i]); -#ifdef HAVE_DLADDR - } - fprintf(stderr, "\n\e[0m"); - } -#endif /* HAVE_DLADDR */ - } - free (strings); -#endif /* HAVE_BACKTRACE */ -} - -/** * Leak report white list * * List of functions using static allocation buffers or should be suppressed * otherwise on leak report. */ char *whitelist[] = { + /* backtraces, including own */ + "backtrace_create", /* pthread stuff */ "pthread_create", "pthread_setspecific", /* glibc functions */ "mktime", "__gmtime_r", + "localtime_r", "tzset", "inet_ntoa", "strerror", @@ -284,27 +204,16 @@ char *whitelist[] = { /** * check if a stack frame contains functions listed above */ -static bool is_whitelisted(void **stack_frames, int stack_frame_count) +static bool is_whitelisted(backtrace_t *backtrace) { - int i, j; - -#ifdef HAVE_DLADDR - for (i=0; i< stack_frame_count; i++) + int i; + for (i = 0; i < sizeof(whitelist)/sizeof(char*); i++) { - Dl_info info; - - if (dladdr(stack_frames[i], &info) && info.dli_sname) - { - for (j = 0; j < sizeof(whitelist)/sizeof(char*); j++) - { - if (streq(info.dli_sname, whitelist[j])) - { - return TRUE; - } - } + if (backtrace->contains_function(backtrace, whitelist[i])) + { + return TRUE; } } -#endif /* HAVE_DLADDR */ return FALSE; } @@ -318,7 +227,7 @@ void report_leaks() for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) { - if (is_whitelisted(hdr->stack_frames, hdr->stack_frame_count)) + if (is_whitelisted(hdr->backtrace)) { whitelisted++; } @@ -326,7 +235,7 @@ void report_leaks() { fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1); /* skip the first frame, contains leak detective logic */ - log_stack_frames(hdr->stack_frames + 1, hdr->stack_frame_count - 1); + hdr->backtrace->log(hdr->backtrace, stderr); leaks++; } } @@ -403,7 +312,7 @@ void *malloc_hook(size_t bytes, const void *caller) hdr->magic = MEMORY_HEADER_MAGIC; hdr->bytes = bytes; - hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT); + hdr->backtrace = backtrace_create(3); tail->magic = MEMORY_TAIL_MAGIC; install_hooks(); @@ -426,10 +335,9 @@ void *malloc_hook(size_t bytes, const void *caller) */ void free_hook(void *ptr, const void *caller) { - void *stack_frames[STACK_FRAMES_COUNT]; - int stack_frame_count; memory_header_t *hdr; memory_tail_t *tail; + backtrace_t *backtrace; pthread_t thread_id = pthread_self(); int oldpolicy; struct sched_param oldparams, params; @@ -455,8 +363,9 @@ void free_hook(void *ptr, const void *caller) fprintf(stderr, "freeing invalid memory (%p): " "header magic 0x%x, tail magic 0x%x:\n", ptr, hdr->magic, tail->magic); - stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); - log_stack_frames(stack_frames, stack_frame_count); + backtrace = backtrace_create(3); + backtrace->log(backtrace, stderr); + backtrace->destroy(backtrace); } else { @@ -466,10 +375,11 @@ void free_hook(void *ptr, const void *caller) hdr->next->previous = hdr->previous; } hdr->previous->next = hdr->next; - + hdr->backtrace->destroy(hdr->backtrace); + /* clear MAGIC, set mem to something remarkable */ memset(hdr, MEMORY_FREE_PATTERN, hdr->bytes + sizeof(memory_header_t)); - + free(hdr); } @@ -483,9 +393,8 @@ void free_hook(void *ptr, const void *caller) void *realloc_hook(void *old, size_t bytes, const void *caller) { memory_header_t *hdr; - void *stack_frames[STACK_FRAMES_COUNT]; - int stack_frame_count; memory_tail_t *tail; + backtrace_t *backtrace; pthread_t thread_id = pthread_self(); int oldpolicy; struct sched_param oldparams, params; @@ -512,8 +421,9 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) fprintf(stderr, "reallocating invalid memory (%p): " "header magic 0x%x, tail magic 0x%x:\n", old, hdr->magic, tail->magic); - stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); - log_stack_frames(stack_frames, stack_frame_count); + backtrace = backtrace_create(3); + backtrace->log(backtrace, stderr); + backtrace->destroy(backtrace); } /* clear tail magic, allocate, set tail magic */ memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic)); @@ -523,7 +433,8 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) /* update statistics */ hdr->bytes = bytes; - hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT); + hdr->backtrace->destroy(hdr->backtrace); + hdr->backtrace = backtrace_create(3); /* update header of linked list neighbours */ if (hdr->next) diff --git a/src/libstrongswan/utils/leak_detective.h b/src/libstrongswan/utils/leak_detective.h index 763814726..3773fb8e5 100644 --- a/src/libstrongswan/utils/leak_detective.h +++ b/src/libstrongswan/utils/leak_detective.h @@ -21,11 +21,6 @@ #ifndef LEAK_DETECTIVE_H_ #define LEAK_DETECTIVE_H_ -/** - * Maximum depth stack frames to register - */ -#define STACK_FRAMES_COUNT 20 - typedef struct leak_detective_t leak_detective_t; /** diff --git a/src/libstrongswan/utils/linked_list.c b/src/libstrongswan/utils/linked_list.c index 80c4e6f9f..068d13f99 100644 --- a/src/libstrongswan/utils/linked_list.c +++ b/src/libstrongswan/utils/linked_list.c @@ -14,7 +14,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: linked_list.c 3841 2008-04-18 11:48:53Z tobias $ + * $Id: linked_list.c 4580 2008-11-05 11:55:17Z martin $ */ #include <stdlib.h> @@ -119,21 +119,6 @@ struct private_iterator_t { * Direction of iterator. */ bool forward; - - /** - * Mutex to use to synchronize access - */ - pthread_mutex_t *mutex; - - /** - * iteration hook - */ - iterator_hook_t *hook; - - /** - * user parameter for iterator hook - */ - void *hook_param; }; typedef struct private_enumerator_t private_enumerator_t; @@ -208,75 +193,23 @@ static int get_list_count(private_iterator_t *this) } /** - * default iterator hook which does nothing - */ -static hook_result_t iterator_hook(void *param, void *in, void **out) -{ - *out = in; - return HOOK_NEXT; -} - -/** - * Implementation of iterator_t.set_iterator_hook. + * Implementation of iterator_t.iterate. */ -static void set_iterator_hook(private_iterator_t *this, iterator_hook_t *hook, - void* param) +static bool iterate(private_iterator_t *this, void** value) { - if (hook == NULL) + if (this->forward) { - this->hook = iterator_hook; - this->hook_param = NULL; + this->current = this->current ? this->current->next : this->list->first; } else { - this->hook = hook; - this->hook_param = param; + this->current = this->current ? this->current->previous : this->list->last; } -} - -/** - * Implementation of iterator_t.iterate. - */ -static bool iterate(private_iterator_t *this, void** value) -{ - while (TRUE) + if (this->current == NULL) { - if (this->forward) - { - this->current = this->current ? this->current->next : this->list->first; - } - else - { - this->current = this->current ? this->current->previous : this->list->last; - } - - if (this->current == NULL) - { - return FALSE; - } - - switch (this->hook(this->hook_param, this->current->value, value)) - { - case HOOK_AGAIN: - /* rewind */ - if (this->forward) - { - this->current = this->current->previous; - } - else - { - this->current = this->current->next; - } - break; - case HOOK_NEXT: - /* normal iteration */ - break; - case HOOK_SKIP: - /* advance */ - continue; - } - break; + return FALSE; } + *value = this->current->value; return TRUE; } @@ -428,10 +361,6 @@ static void insert_after(private_iterator_t *iterator, void *item) */ static void iterator_destroy(private_iterator_t *this) { - if (this->mutex) - { - pthread_mutex_unlock(this->mutex); - } free(this); } @@ -632,7 +561,8 @@ static status_t find_first(private_linked_list_t *this, linked_list_match_t matc while (current) { - if (match(current->value, d1, d2, d3, d4, d5)) + if ((match && match(current->value, d1, d2, d3, d4, d5)) || + (!match && item && current->value == *item)) { if (item != NULL) { @@ -655,7 +585,8 @@ static status_t find_last(private_linked_list_t *this, linked_list_match_t match while (current) { - if (match(current->value, d1, d2, d3, d4, d5)) + if ((match && match(current->value, d1, d2, d3, d4, d5)) || + (!match && item && current->value == *item)) { if (item != NULL) { @@ -793,7 +724,6 @@ static iterator_t *create_iterator(private_linked_list_t *linked_list, bool forw this->public.get_count = (int (*) (iterator_t*)) get_list_count; this->public.iterate = (bool (*) (iterator_t*, void **value)) iterate; - this->public.set_iterator_hook = (void(*)(iterator_t*, iterator_hook_t*, void*))set_iterator_hook; this->public.insert_before = (void (*) (iterator_t*, void *item)) insert_before; this->public.insert_after = (void (*) (iterator_t*, void *item)) insert_after; this->public.replace = (status_t (*) (iterator_t*, void **, void *)) replace; @@ -804,22 +734,6 @@ static iterator_t *create_iterator(private_linked_list_t *linked_list, bool forw this->forward = forward; this->current = NULL; this->list = linked_list; - this->mutex = NULL; - this->hook = iterator_hook; - - return &this->public; -} - -/** - * Implementation of linked_list_t.create_iterator_locked. - */ -static iterator_t *create_iterator_locked(private_linked_list_t *linked_list, - pthread_mutex_t *mutex) -{ - private_iterator_t *this = (private_iterator_t*)create_iterator(linked_list, TRUE); - this->mutex = mutex; - - pthread_mutex_lock(mutex); return &this->public; } @@ -833,7 +747,6 @@ linked_list_t *linked_list_create() this->public.get_count = (int (*) (linked_list_t *)) get_count; this->public.create_iterator = (iterator_t * (*) (linked_list_t *,bool))create_iterator; - this->public.create_iterator_locked = (iterator_t * (*) (linked_list_t *,pthread_mutex_t*))create_iterator_locked; this->public.create_enumerator = (enumerator_t*(*)(linked_list_t*))create_enumerator; this->public.get_first = (status_t (*) (linked_list_t *, void **item))get_first; this->public.get_last = (status_t (*) (linked_list_t *, void **item))get_last; diff --git a/src/libstrongswan/utils/linked_list.h b/src/libstrongswan/utils/linked_list.h index 310e91e3c..ba47e7dfb 100644 --- a/src/libstrongswan/utils/linked_list.h +++ b/src/libstrongswan/utils/linked_list.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2007-2008 Tobias Brunner - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -14,7 +14,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: linked_list.h 3841 2008-04-18 11:48:53Z tobias $ + * $Id: linked_list.h 4576 2008-11-05 08:32:38Z martin $ */ /** @@ -27,13 +27,10 @@ typedef struct linked_list_t linked_list_t; -#include <pthread.h> - #include <library.h> #include <utils/iterator.h> #include <utils/enumerator.h> - /** * Method to match elements in a linked list (used in find_* functions) * @@ -81,18 +78,6 @@ struct linked_list_t { iterator_t *(*create_iterator) (linked_list_t *this, bool forward); /** - * Creates a iterator, locking a mutex. - * - * The supplied mutex is acquired immediately, and released - * when the iterator gets destroyed. - * - * @param mutex mutex to use for exclusive access - * @return new iterator_t object - */ - iterator_t *(*create_iterator_locked) (linked_list_t *this, - pthread_mutex_t *mutex); - - /** * Create an enumerator over the list. * * The enumerator is a "lightweight" iterator. It only has two methods @@ -130,7 +115,7 @@ struct linked_list_t { * If a compare function is given, it is called for each item, where * the first parameter is the current list item and the second parameter * is the supplied item parameter. - * If compare is NULL, compare is is done by pointer. + * If compare is NULL, compare is done by pointer. * * @param item item to remove/pass to comparator * @param compare compare function, or NULL @@ -179,10 +164,12 @@ struct linked_list_t { * If the supplied function returns TRUE this function returns SUCCESS, and * the current object is returned in the third parameter, otherwise, * the next item is checked. + * + * If match is NULL, *item and the current object are compared. * * @warning Only use pointers as user supplied data. * - * @param match comparison function to call on each object + * @param match comparison function to call on each object, or NULL * @param item the list item, if found * @param ... user data to supply to match function (limited to 5 arguments) * @return SUCCESS if found, NOT_FOUND otherwise @@ -198,9 +185,11 @@ struct linked_list_t { * the current object is returned in the third parameter, otherwise, * the next item is checked. * + * If match is NULL, *item and the current object are compared. + * * @warning Only use pointers as user supplied data. * - * @param match comparison function to call on each object + * @param match comparison function to call on each object, or NULL * @param item the list item, if found * @param ... user data to supply to match function (limited to 5 arguments) * @return SUCCESS if found, NOT_FOUND otherwise diff --git a/src/libstrongswan/utils/mutex.c b/src/libstrongswan/utils/mutex.c index 425389b4f..ddb0d2df6 100644 --- a/src/libstrongswan/utils/mutex.c +++ b/src/libstrongswan/utils/mutex.c @@ -12,24 +12,92 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: mutex.c 3589 2008-03-13 14:14:44Z martin $ + * $Id: mutex.c 4591 2008-11-05 16:12:54Z martin $ */ -#include "mutex.h" - -#include <library.h> -#include <debug.h> - +#define _GNU_SOURCE #include <pthread.h> #include <sys/time.h> +#include <stdint.h> #include <time.h> #include <errno.h> +#include "mutex.h" + +#include <library.h> +#include <debug.h> typedef struct private_mutex_t private_mutex_t; -typedef struct private_n_mutex_t private_n_mutex_t; typedef struct private_r_mutex_t private_r_mutex_t; typedef struct private_condvar_t private_condvar_t; +typedef struct private_rwlock_t private_rwlock_t; + +#ifdef LOCK_PROFILER + +/** + * Do not report mutexes with an overall waiting time smaller than this (in us) + */ +#define PROFILE_TRESHHOLD 1000 + +#include <utils/backtrace.h> + +typedef struct lock_profile_t lock_profile_t; + +struct lock_profile_t { + + /** + * how long threads have waited for the lock in this mutex so far + */ + struct timeval waited; + + /** + * backtrace where mutex has been created + */ + backtrace_t *backtrace; +}; + +/** + * Print and cleanup mutex profiler + */ +static void profiler_cleanup(lock_profile_t *profile) +{ + if (profile->waited.tv_sec > 0 || + profile->waited.tv_usec > PROFILE_TRESHHOLD) + { + fprintf(stderr, "%d.%06ds in lock created at:", + profile->waited.tv_sec, profile->waited.tv_usec); + profile->backtrace->log(profile->backtrace, stderr); + } + profile->backtrace->destroy(profile->backtrace); +} + +/** + * Initialize mutex profiler + */ +static void profiler_init(lock_profile_t *profile) +{ + profile->backtrace = backtrace_create(3); + timerclear(&profile->waited); +} + +#define profiler_start(profile) { \ + struct timeval _start, _end, _diff; \ + gettimeofday(&_start, NULL); + +#define profiler_end(profile) \ + gettimeofday(&_end, NULL); \ + timersub(&_end, &_start, &_diff); \ + timeradd(&(profile)->waited, &_diff, &(profile)->waited); } + +#else /* !LOCK_PROFILER */ + +#define lock_profile_t struct {} +#define profiler_cleanup(...) {} +#define profiler_init(...) {} +#define profiler_start(...) {} +#define profiler_end(...) {} + +#endif /* LOCK_PROFILER */ /** * private data of mutex @@ -45,6 +113,16 @@ struct private_mutex_t { * wrapped pthread mutex */ pthread_mutex_t mutex; + + /** + * is this a recursiv emutex, implementing private_r_mutex_t? + */ + bool recursive; + + /** + * profiling info, if enabled + */ + lock_profile_t profile; }; /** @@ -53,7 +131,7 @@ struct private_mutex_t { struct private_r_mutex_t { /** - * public functions + * Extends private_mutex_t */ private_mutex_t generic; @@ -63,9 +141,9 @@ struct private_r_mutex_t { pthread_t thread; /** - * times we have locked the lock + * times we have locked the lock, stored per thread */ - int times; + pthread_key_t times; }; /** @@ -85,14 +163,37 @@ struct private_condvar_t { }; /** + * private data of rwlock + */ +struct private_rwlock_t { + + /** + * public functions + */ + rwlock_t public; + + /** + * wrapped pthread rwlock + */ + pthread_rwlock_t rwlock; + + /** + * profiling info, if enabled + */ + lock_profile_t profile; +}; + +/** * Implementation of mutex_t.lock. */ static void lock(private_mutex_t *this) { + profiler_start(&this->profile); if (pthread_mutex_lock(&this->mutex)) { DBG1("!!!! MUTEX %sLOCK ERROR, your code is buggy !!!", ""); } + profiler_end(&this->profile); } /** @@ -115,12 +216,19 @@ static void lock_r(private_r_mutex_t *this) if (this->thread == self) { - this->times++; - return; + uintptr_t times; + + /* times++ */ + times = (uintptr_t)pthread_getspecific(this->times); + pthread_setspecific(this->times, (void*)times + 1); + } + else + { + lock(&this->generic); + this->thread = self; + /* times = 1 */ + pthread_setspecific(this->times, (void*)1); } - lock(&this->generic); - this->thread = self; - this->times = 1; } /** @@ -128,7 +236,13 @@ static void lock_r(private_r_mutex_t *this) */ static void unlock_r(private_r_mutex_t *this) { - if (--this->times == 0) + uintptr_t times; + + /* times-- */ + times = (uintptr_t)pthread_getspecific(this->times); + pthread_setspecific(this->times, (void*)--times); + + if (times == 0) { this->thread = 0; unlock(&this->generic); @@ -140,10 +254,22 @@ static void unlock_r(private_r_mutex_t *this) */ static void mutex_destroy(private_mutex_t *this) { + profiler_cleanup(&this->profile); pthread_mutex_destroy(&this->mutex); free(this); } +/** + * Implementation of mutex_t.destroy for recursive mutex' + */ +static void mutex_destroy_r(private_r_mutex_t *this) +{ + profiler_cleanup(&this->generic.profile); + pthread_mutex_destroy(&this->generic.mutex); + pthread_key_delete(this->times); + free(this); +} + /* * see header file */ @@ -154,15 +280,17 @@ mutex_t *mutex_create(mutex_type_t type) case MUTEX_RECURSIVE: { private_r_mutex_t *this = malloc_thing(private_r_mutex_t); - + this->generic.public.lock = (void(*)(mutex_t*))lock_r; this->generic.public.unlock = (void(*)(mutex_t*))unlock_r; - this->generic.public.destroy = (void(*)(mutex_t*))mutex_destroy; - + this->generic.public.destroy = (void(*)(mutex_t*))mutex_destroy_r; + pthread_mutex_init(&this->generic.mutex, NULL); + pthread_key_create(&this->times, NULL); + this->generic.recursive = TRUE; + profiler_init(&this->generic.profile); this->thread = 0; - this->times = 0; - + return &this->generic.public; } case MUTEX_DEFAULT: @@ -173,9 +301,11 @@ mutex_t *mutex_create(mutex_type_t type) this->public.lock = (void(*)(mutex_t*))lock; this->public.unlock = (void(*)(mutex_t*))unlock; this->public.destroy = (void(*)(mutex_t*))mutex_destroy; - + pthread_mutex_init(&this->mutex, NULL); - + this->recursive = FALSE; + profiler_init(&this->profile); + return &this->public; } } @@ -186,7 +316,19 @@ mutex_t *mutex_create(mutex_type_t type) */ static void wait(private_condvar_t *this, private_mutex_t *mutex) { - pthread_cond_wait(&this->condvar, &mutex->mutex); + if (mutex->recursive) + { + private_r_mutex_t* recursive = (private_r_mutex_t*)mutex; + + /* mutex owner gets cleared during condvar wait */ + recursive->thread = 0; + pthread_cond_wait(&this->condvar, &mutex->mutex); + recursive->thread = pthread_self(); + } + else + { + pthread_cond_wait(&this->condvar, &mutex->mutex); + } } /** @@ -198,6 +340,7 @@ static bool timed_wait(private_condvar_t *this, private_mutex_t *mutex, struct timespec ts; struct timeval tv; u_int s, ms; + bool timed_out; gettimeofday(&tv, NULL); @@ -211,8 +354,21 @@ static bool timed_wait(private_condvar_t *this, private_mutex_t *mutex, ts.tv_nsec -= 1000000000; ts.tv_sec++; } - return (pthread_cond_timedwait(&this->condvar, &mutex->mutex, - &ts) == ETIMEDOUT); + if (mutex->recursive) + { + private_r_mutex_t* recursive = (private_r_mutex_t*)mutex; + + recursive->thread = 0; + timed_out = pthread_cond_timedwait(&this->condvar, &mutex->mutex, + &ts) == ETIMEDOUT; + recursive->thread = pthread_self(); + } + else + { + timed_out = pthread_cond_timedwait(&this->condvar, &mutex->mutex, + &ts) == ETIMEDOUT; + } + return timed_out; } /** @@ -265,3 +421,75 @@ condvar_t *condvar_create(condvar_type_t type) } } +/** + * Implementation of rwlock_t.read_lock + */ +static void read_lock(private_rwlock_t *this) +{ + profiler_start(&this->profile); + pthread_rwlock_rdlock(&this->rwlock); + profiler_end(&this->profile); +} + +/** + * Implementation of rwlock_t.write_lock + */ +static void write_lock(private_rwlock_t *this) +{ + profiler_start(&this->profile); + pthread_rwlock_wrlock(&this->rwlock); + profiler_end(&this->profile); +} + +/** + * Implementation of rwlock_t.try_write_lock + */ +static bool try_write_lock(private_rwlock_t *this) +{ + return pthread_rwlock_trywrlock(&this->rwlock) == 0; +} + +/** + * Implementation of rwlock_t.unlock + */ +static void rw_unlock(private_rwlock_t *this) +{ + pthread_rwlock_unlock(&this->rwlock); +} + +/** + * Implementation of rwlock_t.destroy + */ +static void rw_destroy(private_rwlock_t *this) +{ + pthread_rwlock_destroy(&this->rwlock); + profiler_cleanup(&this->profile); + free(this); +} + +/* + * see header file + */ +rwlock_t *rwlock_create(rwlock_type_t type) +{ + switch (type) + { + case RWLOCK_DEFAULT: + default: + { + private_rwlock_t *this = malloc_thing(private_rwlock_t); + + this->public.read_lock = (void(*)(rwlock_t*))read_lock; + this->public.write_lock = (void(*)(rwlock_t*))write_lock; + this->public.try_write_lock = (bool(*)(rwlock_t*))try_write_lock; + this->public.unlock = (void(*)(rwlock_t*))rw_unlock; + this->public.destroy = (void(*)(rwlock_t*))rw_destroy; + + pthread_rwlock_init(&this->rwlock, NULL); + profiler_init(&this->profile); + + return &this->public; + } + } +} + diff --git a/src/libstrongswan/utils/mutex.h b/src/libstrongswan/utils/mutex.h index cf557c35c..a0a198024 100644 --- a/src/libstrongswan/utils/mutex.h +++ b/src/libstrongswan/utils/mutex.h @@ -23,8 +23,10 @@ typedef struct mutex_t mutex_t; typedef struct condvar_t condvar_t; +typedef struct rwlock_t rwlock_t; typedef enum mutex_type_t mutex_type_t; typedef enum condvar_type_t condvar_type_t; +typedef enum rwlock_type_t rwlock_type_t; #include <library.h> @@ -47,6 +49,14 @@ enum condvar_type_t { }; /** + * Type of read-write lock. + */ +enum rwlock_type_t { + /** default condvar */ + RWLOCK_DEFAULT = 0, +}; + +/** * Mutex wrapper implements simple, portable and advanced mutex functions. */ struct mutex_t { @@ -105,6 +115,41 @@ struct condvar_t { }; /** + * Read-Write lock wrapper. + */ +struct rwlock_t { + + /** + * Acquire the read lock. + */ + void (*read_lock)(rwlock_t *this); + + /** + * Acquire the write lock. + */ + void (*write_lock)(rwlock_t *this); + + /** + * Try to acquire the write lock. + * + * Never blocks, but returns FALSE if the lock was already occupied. + * + * @return TRUE if lock acquired + */ + bool (*try_write_lock)(rwlock_t *this); + + /** + * Release any acquired lock. + */ + void (*unlock)(rwlock_t *this); + + /** + * Destroy the read-write lock. + */ + void (*destroy)(rwlock_t *this); +}; + +/** * Create a mutex instance. * * @param type type of mutex to create @@ -120,4 +165,12 @@ mutex_t *mutex_create(mutex_type_t type); */ condvar_t *condvar_create(condvar_type_t type); +/** + * Create a read-write lock instance. + * + * @param type type of rwlock to create + * @return unlocked rwlock instance + */ +rwlock_t *rwlock_create(rwlock_type_t type); + #endif /* MUTEX_H_ @}*/ |