summaryrefslogtreecommitdiff
path: root/src/libstrongswan
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan')
-rw-r--r--src/libstrongswan/Android.mk12
-rw-r--r--src/libstrongswan/Makefile.am15
-rw-r--r--src/libstrongswan/Makefile.in167
-rw-r--r--src/libstrongswan/asn1/asn1.c8
-rw-r--r--src/libstrongswan/chunk.c63
-rw-r--r--src/libstrongswan/chunk.h12
-rw-r--r--src/libstrongswan/credentials/auth_cfg.c830
-rw-r--r--src/libstrongswan/credentials/auth_cfg.h255
-rw-r--r--src/libstrongswan/credentials/builder.c1
-rw-r--r--src/libstrongswan/credentials/builder.h2
-rw-r--r--src/libstrongswan/credentials/cert_validator.h51
-rw-r--r--src/libstrongswan/credentials/certificates/certificate.c22
-rw-r--r--src/libstrongswan/credentials/certificates/certificate.h26
-rw-r--r--src/libstrongswan/credentials/certificates/crl.c28
-rw-r--r--src/libstrongswan/credentials/certificates/crl.h10
-rw-r--r--src/libstrongswan/credentials/certificates/x509.h1
-rw-r--r--src/libstrongswan/credentials/cred_encoding.c (renamed from src/libstrongswan/credentials/keys/key_encoding.c)121
-rw-r--r--src/libstrongswan/credentials/cred_encoding.h224
-rw-r--r--src/libstrongswan/credentials/credential_manager.c1097
-rw-r--r--src/libstrongswan/credentials/credential_manager.h270
-rw-r--r--src/libstrongswan/credentials/credential_set.h108
-rw-r--r--src/libstrongswan/credentials/ietf_attributes/ietf_attributes.c13
-rw-r--r--src/libstrongswan/credentials/keys/key_encoding.h203
-rw-r--r--src/libstrongswan/credentials/keys/private_key.c12
-rw-r--r--src/libstrongswan/credentials/keys/private_key.h9
-rw-r--r--src/libstrongswan/credentials/keys/public_key.c8
-rw-r--r--src/libstrongswan/credentials/keys/public_key.h11
-rw-r--r--src/libstrongswan/credentials/sets/auth_cfg_wrapper.c223
-rw-r--r--src/libstrongswan/credentials/sets/auth_cfg_wrapper.h53
-rw-r--r--src/libstrongswan/credentials/sets/cert_cache.c389
-rw-r--r--src/libstrongswan/credentials/sets/cert_cache.h71
-rw-r--r--src/libstrongswan/credentials/sets/ocsp_response_wrapper.c146
-rw-r--r--src/libstrongswan/credentials/sets/ocsp_response_wrapper.h53
-rw-r--r--src/libstrongswan/library.c22
-rw-r--r--src/libstrongswan/library.h15
-rw-r--r--src/libstrongswan/plugins/aes/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/agent/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/agent/agent_private_key.c10
-rw-r--r--src/libstrongswan/plugins/blowfish/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/curl/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/des/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/dnskey/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/fips_prf/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/gcrypt/Makefile.am2
-rw-r--r--src/libstrongswan/plugins/gcrypt/Makefile.in4
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c22
-rw-r--r--src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c16
-rw-r--r--src/libstrongswan/plugins/gmp/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c20
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c12
-rw-r--r--src/libstrongswan/plugins/hmac/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/ldap/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/md4/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/md5/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/mysql/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/openssl/Makefile.am4
-rw-r--r--src/libstrongswan/plugins/openssl/Makefile.in10
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_crl.c530
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_crl.h48
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c6
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_ec_private_key.c27
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_ec_public_key.c31
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_plugin.c36
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c28
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c44
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_sha1_prf.h2
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_util.c83
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_util.h56
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_x509.c871
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_x509.h50
-rw-r--r--src/libstrongswan/plugins/padlock/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/pem/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/pem/pem_builder.c2
-rw-r--r--src/libstrongswan/plugins/pem/pem_encoder.c73
-rw-r--r--src/libstrongswan/plugins/pem/pem_encoder.h4
-rw-r--r--src/libstrongswan/plugins/pgp/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_cert.c38
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_encoder.c10
-rw-r--r--src/libstrongswan/plugins/pgp/pgp_encoder.h4
-rw-r--r--src/libstrongswan/plugins/pkcs1/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c30
-rw-r--r--src/libstrongswan/plugins/pkcs1/pkcs1_encoder.h4
-rw-r--r--src/libstrongswan/plugins/plugin_loader.c3
-rw-r--r--src/libstrongswan/plugins/pubkey/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/pubkey/pubkey_cert.c28
-rw-r--r--src/libstrongswan/plugins/random/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/revocation/Makefile.am16
-rw-r--r--src/libstrongswan/plugins/revocation/Makefile.in588
-rw-r--r--src/libstrongswan/plugins/revocation/revocation_plugin.c61
-rw-r--r--src/libstrongswan/plugins/revocation/revocation_plugin.h42
-rw-r--r--src/libstrongswan/plugins/revocation/revocation_validator.c587
-rw-r--r--src/libstrongswan/plugins/revocation/revocation_validator.h49
-rw-r--r--src/libstrongswan/plugins/sha1/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/sha2/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/sqlite/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/test_vectors/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/x509/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/x509/x509_ac.c42
-rw-r--r--src/libstrongswan/plugins/x509/x509_cert.c56
-rw-r--r--src/libstrongswan/plugins/x509/x509_crl.c366
-rw-r--r--src/libstrongswan/plugins/x509/x509_crl.h9
-rw-r--r--src/libstrongswan/plugins/x509/x509_ocsp_request.c28
-rw-r--r--src/libstrongswan/plugins/x509/x509_ocsp_response.c42
-rw-r--r--src/libstrongswan/plugins/x509/x509_pkcs10.c33
-rw-r--r--src/libstrongswan/plugins/x509/x509_plugin.c4
-rw-r--r--src/libstrongswan/plugins/xcbc/Makefile.in2
-rw-r--r--src/libstrongswan/threading/lock_profiler.h2
-rw-r--r--src/libstrongswan/utils/backtrace.c42
-rw-r--r--src/libstrongswan/utils/backtrace.h5
-rw-r--r--src/libstrongswan/utils/hashtable.c135
-rw-r--r--src/libstrongswan/utils/hashtable.h14
-rw-r--r--src/libstrongswan/utils/identification.c16
-rw-r--r--src/libstrongswan/utils/identification.h5
-rw-r--r--src/libstrongswan/utils/leak_detective.c61
-rw-r--r--src/libstrongswan/utils/leak_detective.h9
115 files changed, 7983 insertions, 938 deletions
diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk
index d639220e3..1931dfa45 100644
--- a/src/libstrongswan/Android.mk
+++ b/src/libstrongswan/Android.mk
@@ -26,7 +26,7 @@ crypto/diffie_hellman.c crypto/diffie_hellman.h \
crypto/transform.c crypto/transform.h \
credentials/credential_factory.c credentials/credential_factory.h \
credentials/builder.c credentials/builder.h \
-credentials/keys/key_encoding.c credentials/keys/key_encoding.h \
+credentials/cred_encoding.c credentials/cred_encoding.h \
credentials/keys/private_key.c credentials/keys/private_key.h \
credentials/keys/public_key.c credentials/keys/public_key.h \
credentials/keys/shared_key.c credentials/keys/shared_key.h \
@@ -39,6 +39,12 @@ credentials/certificates/ocsp_request.h \
credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \
credentials/certificates/pgp_certificate.h \
credentials/ietf_attributes/ietf_attributes.c credentials/ietf_attributes/ietf_attributes.h \
+credentials/credential_manager.c credentials/credential_manager.h \
+credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \
+credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \
+credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
+credentials/auth_cfg.c credentials/auth_cfg.h credentials/credential_set.h \
+credentials/cert_validator.h \
database/database.h database/database_factory.h database/database_factory.c \
fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
selectors/traffic_selector.c selectors/traffic_selector.h \
@@ -68,7 +74,7 @@ LOCAL_SRC_FILES += $(call add_plugin, des)
LOCAL_SRC_FILES += $(call add_plugin, fips-prf)
LOCAL_SRC_FILES += $(call add_plugin, gmp)
-ifneq ($(call plugin_enabled, gmp)),)
+ifneq ($(call plugin_enabled, gmp),)
LOCAL_C_INCLUDES += $(libgmp_PATH)
LOCAL_SHARED_LIBRARIES += libgmp
endif
@@ -80,7 +86,7 @@ LOCAL_SRC_FILES += $(call add_plugin, md4)
LOCAL_SRC_FILES += $(call add_plugin, md5)
LOCAL_SRC_FILES += $(call add_plugin, openssl)
-ifneq ($(call plugin_enabled, openssl)),)
+ifneq ($(call plugin_enabled, openssl),)
LOCAL_C_INCLUDES += external/openssl/include
LOCAL_SHARED_LIBRARIES += libcrypto
endif
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index 157d37b5e..3678abd5d 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -24,7 +24,7 @@ crypto/diffie_hellman.c crypto/diffie_hellman.h \
crypto/transform.c crypto/transform.h \
credentials/credential_factory.c credentials/credential_factory.h \
credentials/builder.c credentials/builder.h \
-credentials/keys/key_encoding.c credentials/keys/key_encoding.h \
+credentials/cred_encoding.c credentials/cred_encoding.h \
credentials/keys/private_key.c credentials/keys/private_key.h \
credentials/keys/public_key.c credentials/keys/public_key.h \
credentials/keys/shared_key.c credentials/keys/shared_key.h \
@@ -37,6 +37,12 @@ credentials/certificates/ocsp_request.h \
credentials/certificates/ocsp_response.h credentials/certificates/ocsp_response.c \
credentials/certificates/pgp_certificate.h \
credentials/ietf_attributes/ietf_attributes.c credentials/ietf_attributes/ietf_attributes.h \
+credentials/credential_manager.c credentials/credential_manager.h \
+credentials/sets/auth_cfg_wrapper.c credentials/sets/auth_cfg_wrapper.h \
+credentials/sets/ocsp_response_wrapper.c credentials/sets/ocsp_response_wrapper.h \
+credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
+credentials/auth_cfg.c credentials/auth_cfg.h credentials/credential_set.h \
+credentials/cert_validator.h \
database/database.h database/database_factory.h database/database_factory.c \
fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
selectors/traffic_selector.c selectors/traffic_selector.h \
@@ -203,6 +209,13 @@ if MONOLITHIC
endif
endif
+if USE_REVOCATION
+ SUBDIRS += plugins/revocation
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/revocation/libstrongswan-revocation.la
+endif
+endif
+
if USE_PUBKEY
SUBDIRS += plugins/pubkey
if MONOLITHIC
diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in
index b8d967d4a..b6dcf6be5 100644
--- a/src/libstrongswan/Makefile.in
+++ b/src/libstrongswan/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -68,36 +68,38 @@ host_triplet = @host@
@MONOLITHIC_TRUE@@USE_XCBC_TRUE@am__append_28 = plugins/xcbc/libstrongswan-xcbc.la
@USE_X509_TRUE@am__append_29 = plugins/x509
@MONOLITHIC_TRUE@@USE_X509_TRUE@am__append_30 = plugins/x509/libstrongswan-x509.la
-@USE_PUBKEY_TRUE@am__append_31 = plugins/pubkey
-@MONOLITHIC_TRUE@@USE_PUBKEY_TRUE@am__append_32 = plugins/pubkey/libstrongswan-pubkey.la
-@USE_PKCS1_TRUE@am__append_33 = plugins/pkcs1
-@MONOLITHIC_TRUE@@USE_PKCS1_TRUE@am__append_34 = plugins/pkcs1/libstrongswan-pkcs1.la
-@USE_PGP_TRUE@am__append_35 = plugins/pgp
-@MONOLITHIC_TRUE@@USE_PGP_TRUE@am__append_36 = plugins/pgp/libstrongswan-pgp.la
-@USE_DNSKEY_TRUE@am__append_37 = plugins/dnskey
-@MONOLITHIC_TRUE@@USE_DNSKEY_TRUE@am__append_38 = plugins/dnskey/libstrongswan-dnskey.la
-@USE_PEM_TRUE@am__append_39 = plugins/pem
-@MONOLITHIC_TRUE@@USE_PEM_TRUE@am__append_40 = plugins/pem/libstrongswan-pem.la
-@USE_CURL_TRUE@am__append_41 = plugins/curl
-@MONOLITHIC_TRUE@@USE_CURL_TRUE@am__append_42 = plugins/curl/libstrongswan-curl.la
-@USE_LDAP_TRUE@am__append_43 = plugins/ldap
-@MONOLITHIC_TRUE@@USE_LDAP_TRUE@am__append_44 = plugins/ldap/libstrongswan-ldap.la
-@USE_MYSQL_TRUE@am__append_45 = plugins/mysql
-@MONOLITHIC_TRUE@@USE_MYSQL_TRUE@am__append_46 = plugins/mysql/libstrongswan-mysql.la
-@USE_SQLITE_TRUE@am__append_47 = plugins/sqlite
-@MONOLITHIC_TRUE@@USE_SQLITE_TRUE@am__append_48 = plugins/sqlite/libstrongswan-sqlite.la
-@USE_PADLOCK_TRUE@am__append_49 = plugins/padlock
-@MONOLITHIC_TRUE@@USE_PADLOCK_TRUE@am__append_50 = plugins/padlock/libstrongswan-padlock.la
-@USE_OPENSSL_TRUE@am__append_51 = plugins/openssl
-@MONOLITHIC_TRUE@@USE_OPENSSL_TRUE@am__append_52 = plugins/openssl/libstrongswan-openssl.la
-@USE_GCRYPT_TRUE@am__append_53 = plugins/gcrypt
-@MONOLITHIC_TRUE@@USE_GCRYPT_TRUE@am__append_54 = plugins/gcrypt/libstrongswan-gcrypt.la
-@USE_FIPS_PRF_TRUE@am__append_55 = plugins/fips_prf
-@MONOLITHIC_TRUE@@USE_FIPS_PRF_TRUE@am__append_56 = plugins/fips_prf/libstrongswan-fips-prf.la
-@USE_AGENT_TRUE@am__append_57 = plugins/agent
-@MONOLITHIC_TRUE@@USE_AGENT_TRUE@am__append_58 = plugins/agent/libstrongswan-agent.la
-@USE_TEST_VECTORS_TRUE@am__append_59 = plugins/test_vectors
-@MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE@am__append_60 = plugins/test_vectors/libstrongswan-test-vectors.la
+@USE_REVOCATION_TRUE@am__append_31 = plugins/revocation
+@MONOLITHIC_TRUE@@USE_REVOCATION_TRUE@am__append_32 = plugins/revocation/libstrongswan-revocation.la
+@USE_PUBKEY_TRUE@am__append_33 = plugins/pubkey
+@MONOLITHIC_TRUE@@USE_PUBKEY_TRUE@am__append_34 = plugins/pubkey/libstrongswan-pubkey.la
+@USE_PKCS1_TRUE@am__append_35 = plugins/pkcs1
+@MONOLITHIC_TRUE@@USE_PKCS1_TRUE@am__append_36 = plugins/pkcs1/libstrongswan-pkcs1.la
+@USE_PGP_TRUE@am__append_37 = plugins/pgp
+@MONOLITHIC_TRUE@@USE_PGP_TRUE@am__append_38 = plugins/pgp/libstrongswan-pgp.la
+@USE_DNSKEY_TRUE@am__append_39 = plugins/dnskey
+@MONOLITHIC_TRUE@@USE_DNSKEY_TRUE@am__append_40 = plugins/dnskey/libstrongswan-dnskey.la
+@USE_PEM_TRUE@am__append_41 = plugins/pem
+@MONOLITHIC_TRUE@@USE_PEM_TRUE@am__append_42 = plugins/pem/libstrongswan-pem.la
+@USE_CURL_TRUE@am__append_43 = plugins/curl
+@MONOLITHIC_TRUE@@USE_CURL_TRUE@am__append_44 = plugins/curl/libstrongswan-curl.la
+@USE_LDAP_TRUE@am__append_45 = plugins/ldap
+@MONOLITHIC_TRUE@@USE_LDAP_TRUE@am__append_46 = plugins/ldap/libstrongswan-ldap.la
+@USE_MYSQL_TRUE@am__append_47 = plugins/mysql
+@MONOLITHIC_TRUE@@USE_MYSQL_TRUE@am__append_48 = plugins/mysql/libstrongswan-mysql.la
+@USE_SQLITE_TRUE@am__append_49 = plugins/sqlite
+@MONOLITHIC_TRUE@@USE_SQLITE_TRUE@am__append_50 = plugins/sqlite/libstrongswan-sqlite.la
+@USE_PADLOCK_TRUE@am__append_51 = plugins/padlock
+@MONOLITHIC_TRUE@@USE_PADLOCK_TRUE@am__append_52 = plugins/padlock/libstrongswan-padlock.la
+@USE_OPENSSL_TRUE@am__append_53 = plugins/openssl
+@MONOLITHIC_TRUE@@USE_OPENSSL_TRUE@am__append_54 = plugins/openssl/libstrongswan-openssl.la
+@USE_GCRYPT_TRUE@am__append_55 = plugins/gcrypt
+@MONOLITHIC_TRUE@@USE_GCRYPT_TRUE@am__append_56 = plugins/gcrypt/libstrongswan-gcrypt.la
+@USE_FIPS_PRF_TRUE@am__append_57 = plugins/fips_prf
+@MONOLITHIC_TRUE@@USE_FIPS_PRF_TRUE@am__append_58 = plugins/fips_prf/libstrongswan-fips-prf.la
+@USE_AGENT_TRUE@am__append_59 = plugins/agent
+@MONOLITHIC_TRUE@@USE_AGENT_TRUE@am__append_60 = plugins/agent/libstrongswan-agent.la
+@USE_TEST_VECTORS_TRUE@am__append_61 = plugins/test_vectors
+@MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE@am__append_62 = plugins/test_vectors/libstrongswan-test-vectors.la
subdir = src/libstrongswan
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -150,7 +152,7 @@ libstrongswan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(am__append_42) $(am__append_44) $(am__append_46) \
$(am__append_48) $(am__append_50) $(am__append_52) \
$(am__append_54) $(am__append_56) $(am__append_58) \
- $(am__append_60)
+ $(am__append_60) $(am__append_62)
am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \
chunk.h debug.c debug.h enum.c enum.h settings.h settings.c \
printf_hook.c printf_hook.h asn1/asn1.c asn1/asn1.h \
@@ -167,8 +169,8 @@ am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \
crypto/diffie_hellman.h crypto/transform.c crypto/transform.h \
credentials/credential_factory.c \
credentials/credential_factory.h credentials/builder.c \
- credentials/builder.h credentials/keys/key_encoding.c \
- credentials/keys/key_encoding.h credentials/keys/private_key.c \
+ credentials/builder.h credentials/cred_encoding.c \
+ credentials/cred_encoding.h credentials/keys/private_key.c \
credentials/keys/private_key.h credentials/keys/public_key.c \
credentials/keys/public_key.h credentials/keys/shared_key.c \
credentials/keys/shared_key.h \
@@ -184,6 +186,15 @@ am__libstrongswan_la_SOURCES_DIST = library.c library.h chunk.c \
credentials/certificates/pgp_certificate.h \
credentials/ietf_attributes/ietf_attributes.c \
credentials/ietf_attributes/ietf_attributes.h \
+ credentials/credential_manager.c \
+ credentials/credential_manager.h \
+ credentials/sets/auth_cfg_wrapper.c \
+ credentials/sets/auth_cfg_wrapper.h \
+ credentials/sets/ocsp_response_wrapper.c \
+ credentials/sets/ocsp_response_wrapper.h \
+ credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
+ credentials/auth_cfg.c credentials/auth_cfg.h \
+ credentials/credential_set.h credentials/cert_validator.h \
database/database.h database/database_factory.h \
database/database_factory.c fetcher/fetcher.h \
fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
@@ -208,9 +219,11 @@ am_libstrongswan_la_OBJECTS = library.lo chunk.lo debug.lo enum.lo \
crypter.lo hasher.lo pkcs9.lo proposal_keywords.lo prf.lo \
rng.lo prf_plus.lo signer.lo crypto_factory.lo \
crypto_tester.lo diffie_hellman.lo transform.lo \
- credential_factory.lo builder.lo key_encoding.lo \
+ credential_factory.lo builder.lo cred_encoding.lo \
private_key.lo public_key.lo shared_key.lo certificate.lo \
x509.lo crl.lo ocsp_response.lo ietf_attributes.lo \
+ credential_manager.lo auth_cfg_wrapper.lo \
+ ocsp_response_wrapper.lo cert_cache.lo auth_cfg.lo \
database_factory.lo fetcher_manager.lo traffic_selector.lo \
thread.lo thread_value.lo mutex.lo rwlock.lo utils.lo host.lo \
identification.lo lexparser.lo linked_list.lo hashtable.lo \
@@ -249,10 +262,11 @@ CTAGS = ctags
DIST_SUBDIRS = . plugins/aes plugins/des plugins/blowfish plugins/md4 \
plugins/md5 plugins/sha1 plugins/sha2 plugins/gmp \
plugins/random plugins/hmac plugins/xcbc plugins/x509 \
- plugins/pubkey plugins/pkcs1 plugins/pgp plugins/dnskey \
- plugins/pem plugins/curl plugins/ldap plugins/mysql \
- plugins/sqlite plugins/padlock plugins/openssl plugins/gcrypt \
- plugins/fips_prf plugins/agent plugins/test_vectors
+ plugins/revocation plugins/pubkey plugins/pkcs1 plugins/pgp \
+ plugins/dnskey plugins/pem plugins/curl plugins/ldap \
+ plugins/mysql plugins/sqlite plugins/padlock plugins/openssl \
+ plugins/gcrypt plugins/fips_prf plugins/agent \
+ plugins/test_vectors
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -451,8 +465,8 @@ libstrongswan_la_SOURCES = library.c library.h chunk.c chunk.h debug.c \
crypto/diffie_hellman.h crypto/transform.c crypto/transform.h \
credentials/credential_factory.c \
credentials/credential_factory.h credentials/builder.c \
- credentials/builder.h credentials/keys/key_encoding.c \
- credentials/keys/key_encoding.h credentials/keys/private_key.c \
+ credentials/builder.h credentials/cred_encoding.c \
+ credentials/cred_encoding.h credentials/keys/private_key.c \
credentials/keys/private_key.h credentials/keys/public_key.c \
credentials/keys/public_key.h credentials/keys/shared_key.c \
credentials/keys/shared_key.h \
@@ -468,6 +482,15 @@ libstrongswan_la_SOURCES = library.c library.h chunk.c chunk.h debug.c \
credentials/certificates/pgp_certificate.h \
credentials/ietf_attributes/ietf_attributes.c \
credentials/ietf_attributes/ietf_attributes.h \
+ credentials/credential_manager.c \
+ credentials/credential_manager.h \
+ credentials/sets/auth_cfg_wrapper.c \
+ credentials/sets/auth_cfg_wrapper.h \
+ credentials/sets/ocsp_response_wrapper.c \
+ credentials/sets/ocsp_response_wrapper.h \
+ credentials/sets/cert_cache.c credentials/sets/cert_cache.h \
+ credentials/auth_cfg.c credentials/auth_cfg.h \
+ credentials/credential_set.h credentials/cert_validator.h \
database/database.h database/database_factory.h \
database/database_factory.c fetcher/fetcher.h \
fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
@@ -494,7 +517,7 @@ libstrongswan_la_LIBADD = $(PTHREADLIB) $(DLLIB) $(BTLIB) $(SOCKLIB) \
$(am__append_42) $(am__append_44) $(am__append_46) \
$(am__append_48) $(am__append_50) $(am__append_52) \
$(am__append_54) $(am__append_56) $(am__append_58) \
- $(am__append_60)
+ $(am__append_60) $(am__append_62)
INCLUDES = -I$(top_srcdir)/src/libstrongswan
AM_CFLAGS = -DIPSEC_DIR=\"${ipsecdir}\" -DPLUGINDIR=\"${plugindir}\" \
-DSTRONGSWAN_CONF=\"${strongswan_conf}\" $(am__append_1) \
@@ -525,7 +548,7 @@ $(srcdir)/crypto/proposal/proposal_keywords.c
@MONOLITHIC_FALSE@ $(am__append_47) $(am__append_49) \
@MONOLITHIC_FALSE@ $(am__append_51) $(am__append_53) \
@MONOLITHIC_FALSE@ $(am__append_55) $(am__append_57) \
-@MONOLITHIC_FALSE@ $(am__append_59)
+@MONOLITHIC_FALSE@ $(am__append_59) $(am__append_61)
# build plugins with their own Makefile
#######################################
@@ -542,7 +565,7 @@ $(srcdir)/crypto/proposal/proposal_keywords.c
@MONOLITHIC_TRUE@ $(am__append_47) $(am__append_49) \
@MONOLITHIC_TRUE@ $(am__append_51) $(am__append_53) \
@MONOLITHIC_TRUE@ $(am__append_55) $(am__append_57) \
-@MONOLITHIC_TRUE@ $(am__append_59)
+@MONOLITHIC_TRUE@ $(am__append_59) $(am__append_61)
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-recursive
@@ -620,11 +643,16 @@ 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)/auth_cfg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/auth_cfg_wrapper.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)/cert_cache.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@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cred_encoding.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/credential_factory.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/credential_manager.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypter.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_factory.Plo@am__quote@
@@ -641,13 +669,13 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/identification.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ietf_attributes.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/integrity_checker.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key_encoding.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/leak_detective.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lexparser.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/library.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/linked_list.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mutex.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_response.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ocsp_response_wrapper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oid.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/optionsfrom.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pkcs9.Plo@am__quote@
@@ -810,12 +838,12 @@ builder.lo: credentials/builder.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 builder.lo `test -f 'credentials/builder.c' || echo '$(srcdir)/'`credentials/builder.c
-key_encoding.lo: credentials/keys/key_encoding.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT key_encoding.lo -MD -MP -MF $(DEPDIR)/key_encoding.Tpo -c -o key_encoding.lo `test -f 'credentials/keys/key_encoding.c' || echo '$(srcdir)/'`credentials/keys/key_encoding.c
-@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/key_encoding.Tpo $(DEPDIR)/key_encoding.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/keys/key_encoding.c' object='key_encoding.lo' libtool=yes @AMDEPBACKSLASH@
+cred_encoding.lo: credentials/cred_encoding.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cred_encoding.lo -MD -MP -MF $(DEPDIR)/cred_encoding.Tpo -c -o cred_encoding.lo `test -f 'credentials/cred_encoding.c' || echo '$(srcdir)/'`credentials/cred_encoding.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cred_encoding.Tpo $(DEPDIR)/cred_encoding.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/cred_encoding.c' object='cred_encoding.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 key_encoding.lo `test -f 'credentials/keys/key_encoding.c' || echo '$(srcdir)/'`credentials/keys/key_encoding.c
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o cred_encoding.lo `test -f 'credentials/cred_encoding.c' || echo '$(srcdir)/'`credentials/cred_encoding.c
private_key.lo: credentials/keys/private_key.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT private_key.lo -MD -MP -MF $(DEPDIR)/private_key.Tpo -c -o private_key.lo `test -f 'credentials/keys/private_key.c' || echo '$(srcdir)/'`credentials/keys/private_key.c
@@ -873,6 +901,41 @@ ietf_attributes.lo: credentials/ietf_attributes/ietf_attributes.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 ietf_attributes.lo `test -f 'credentials/ietf_attributes/ietf_attributes.c' || echo '$(srcdir)/'`credentials/ietf_attributes/ietf_attributes.c
+credential_manager.lo: credentials/credential_manager.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT credential_manager.lo -MD -MP -MF $(DEPDIR)/credential_manager.Tpo -c -o credential_manager.lo `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/credential_manager.Tpo $(DEPDIR)/credential_manager.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/credential_manager.c' object='credential_manager.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 credential_manager.lo `test -f 'credentials/credential_manager.c' || echo '$(srcdir)/'`credentials/credential_manager.c
+
+auth_cfg_wrapper.lo: credentials/sets/auth_cfg_wrapper.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg_wrapper.lo -MD -MP -MF $(DEPDIR)/auth_cfg_wrapper.Tpo -c -o auth_cfg_wrapper.lo `test -f 'credentials/sets/auth_cfg_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_cfg_wrapper.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg_wrapper.Tpo $(DEPDIR)/auth_cfg_wrapper.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/auth_cfg_wrapper.c' object='auth_cfg_wrapper.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 auth_cfg_wrapper.lo `test -f 'credentials/sets/auth_cfg_wrapper.c' || echo '$(srcdir)/'`credentials/sets/auth_cfg_wrapper.c
+
+ocsp_response_wrapper.lo: credentials/sets/ocsp_response_wrapper.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ocsp_response_wrapper.lo -MD -MP -MF $(DEPDIR)/ocsp_response_wrapper.Tpo -c -o ocsp_response_wrapper.lo `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/ocsp_response_wrapper.Tpo $(DEPDIR)/ocsp_response_wrapper.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/ocsp_response_wrapper.c' object='ocsp_response_wrapper.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 ocsp_response_wrapper.lo `test -f 'credentials/sets/ocsp_response_wrapper.c' || echo '$(srcdir)/'`credentials/sets/ocsp_response_wrapper.c
+
+cert_cache.lo: credentials/sets/cert_cache.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT cert_cache.lo -MD -MP -MF $(DEPDIR)/cert_cache.Tpo -c -o cert_cache.lo `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/cert_cache.Tpo $(DEPDIR)/cert_cache.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/sets/cert_cache.c' object='cert_cache.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 cert_cache.lo `test -f 'credentials/sets/cert_cache.c' || echo '$(srcdir)/'`credentials/sets/cert_cache.c
+
+auth_cfg.lo: credentials/auth_cfg.c
+@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT auth_cfg.lo -MD -MP -MF $(DEPDIR)/auth_cfg.Tpo -c -o auth_cfg.lo `test -f 'credentials/auth_cfg.c' || echo '$(srcdir)/'`credentials/auth_cfg.c
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/auth_cfg.Tpo $(DEPDIR)/auth_cfg.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='credentials/auth_cfg.c' object='auth_cfg.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 auth_cfg.lo `test -f 'credentials/auth_cfg.c' || echo '$(srcdir)/'`credentials/auth_cfg.c
+
database_factory.lo: database/database_factory.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT database_factory.lo -MD -MP -MF $(DEPDIR)/database_factory.Tpo -c -o database_factory.lo `test -f 'database/database_factory.c' || echo '$(srcdir)/'`database/database_factory.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/database_factory.Tpo $(DEPDIR)/database_factory.Plo
@@ -1005,7 +1068,7 @@ clean-libtool:
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
$(RECURSIVE_TARGETS):
- @failcom='exit 1'; \
+ @fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
@@ -1030,7 +1093,7 @@ $(RECURSIVE_TARGETS):
fi; test -z "$$fail"
$(RECURSIVE_CLEAN_TARGETS):
- @failcom='exit 1'; \
+ @fail= failcom='exit 1'; \
for f in x $$MAKEFLAGS; do \
case $$f in \
*=* | --[!k]*);; \
diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c
index 6264bdc54..6f549d42d 100644
--- a/src/libstrongswan/asn1/asn1.c
+++ b/src/libstrongswan/asn1/asn1.c
@@ -497,8 +497,14 @@ int asn1_parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters
bool is_asn1(chunk_t blob)
{
u_int len;
- u_char tag = *blob.ptr;
+ u_char tag;
+ if (!blob.len || !blob.ptr)
+ {
+ return FALSE;
+ }
+
+ tag = *blob.ptr;
if (tag != ASN1_SEQUENCE && tag != ASN1_SET && tag != ASN1_OCTET_STRING)
{
DBG2(DBG_LIB, " file content is not binary ASN.1");
diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c
index ef69eb4e7..4d115a816 100644
--- a/src/libstrongswan/chunk.c
+++ b/src/libstrongswan/chunk.c
@@ -434,6 +434,69 @@ chunk_t chunk_from_base64(chunk_t base64, char *buf)
return chunk_create(buf, outlen);
}
+/** base 32 conversion digits */
+static char b32digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
+
+/**
+ * Described in header.
+ */
+chunk_t chunk_to_base32(chunk_t chunk, char *buf)
+{
+ int i, len;
+ char *pos;
+
+ len = chunk.len + ((5 - chunk.len % 5) % 5);
+ if (!buf)
+ {
+ buf = malloc(len * 8 / 5 + 1);
+ }
+ pos = buf;
+ for (i = 0; i < len; i+=5)
+ {
+ *pos++ = b32digits[chunk.ptr[i] >> 3];
+ if (i+1 >= chunk.len)
+ {
+ *pos++ = b32digits[(chunk.ptr[i] & 0x07) << 2];
+ memset(pos, '=', 6);
+ pos += 6;
+ break;
+ }
+ *pos++ = b32digits[((chunk.ptr[i] & 0x07) << 2) |
+ (chunk.ptr[i+1] >> 6)];
+ *pos++ = b32digits[(chunk.ptr[i+1] & 0x3E) >> 1];
+ if (i+2 >= chunk.len)
+ {
+ *pos++ = b32digits[(chunk.ptr[i+1] & 0x01) << 4];
+ memset(pos, '=', 4);
+ pos += 4;
+ break;
+ }
+ *pos++ = b32digits[((chunk.ptr[i+1] & 0x01) << 4) |
+ (chunk.ptr[i+2] >> 4)];
+ if (i+3 >= chunk.len)
+ {
+ *pos++ = b32digits[(chunk.ptr[i+2] & 0x0F) << 1];
+ memset(pos, '=', 3);
+ pos += 3;
+ break;
+ }
+ *pos++ = b32digits[((chunk.ptr[i+2] & 0x0F) << 1) |
+ (chunk.ptr[i+3] >> 7)];
+ *pos++ = b32digits[(chunk.ptr[i+3] & 0x7F) >> 2];
+ if (i+4 >= chunk.len)
+ {
+ *pos++ = b32digits[(chunk.ptr[i+3] & 0x03) << 3];
+ *pos++ = '=';
+ break;
+ }
+ *pos++ = b32digits[((chunk.ptr[i+3] & 0x03) << 3) |
+ (chunk.ptr[i+4] >> 5)];
+ *pos++ = b32digits[chunk.ptr[i+4] & 0x1F];
+ }
+ *pos = '\0';
+ return chunk_create(buf, len * 8 / 5);
+}
+
/**
* Described in header.
*/
diff --git a/src/libstrongswan/chunk.h b/src/libstrongswan/chunk.h
index f0f9a7366..5441ccf3c 100644
--- a/src/libstrongswan/chunk.h
+++ b/src/libstrongswan/chunk.h
@@ -148,6 +148,18 @@ chunk_t chunk_to_base64(chunk_t chunk, char *buf);
chunk_t chunk_from_base64(chunk_t base64, char *buf);
/**
+ * Convert a chunk of data to its base32 encoding.
+ *
+ * The resulting string is '\\0' terminated, but the chunk does not include
+ * the '\\0'. If buf is supplied, it must hold (chunk.len * 8 / 5 + 1) bytes.
+ *
+ * @param chunk data to convert
+ * @param buf buffer to write to, NULL to malloc
+ * @return chunk of encoded data
+ */
+chunk_t chunk_to_base32(chunk_t chunk, char *buf);
+
+/**
* Free contents of a chunk
*/
static inline void chunk_free(chunk_t *chunk)
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c
new file mode 100644
index 000000000..2573d0327
--- /dev/null
+++ b/src/libstrongswan/credentials/auth_cfg.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright (C) 2007-2009 Martin Willi
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "auth_cfg.h"
+
+#include <library.h>
+#include <debug.h>
+#include <utils/linked_list.h>
+#include <utils/identification.h>
+#include <credentials/certificates/certificate.h>
+
+ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_EAP,
+ "any",
+ "public key",
+ "pre-shared key",
+ "EAP",
+);
+
+ENUM_BEGIN(eap_type_names, EAP_IDENTITY, EAP_GTC,
+ "EAP_IDENTITY",
+ "EAP_NOTIFICATION",
+ "EAP_NAK",
+ "EAP_MD5",
+ "EAP_OTP",
+ "EAP_GTC");
+ENUM_NEXT(eap_type_names, EAP_SIM, EAP_SIM, EAP_GTC,
+ "EAP_SIM");
+ENUM_NEXT(eap_type_names, EAP_AKA, EAP_AKA, EAP_SIM,
+ "EAP_AKA");
+ENUM_NEXT(eap_type_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA,
+ "EAP_MSCHAPV2");
+ENUM_NEXT(eap_type_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2,
+ "EAP_RADIUS",
+ "EAP_EXPANDED",
+ "EAP_EXPERIMENTAL");
+ENUM_END(eap_type_names, EAP_EXPERIMENTAL);
+
+ENUM_BEGIN(eap_type_short_names, EAP_IDENTITY, EAP_GTC,
+ "ID",
+ "NTF",
+ "NAK",
+ "MD5",
+ "OTP",
+ "GTC");
+ENUM_NEXT(eap_type_short_names, EAP_SIM, EAP_SIM, EAP_GTC,
+ "SIM");
+ENUM_NEXT(eap_type_short_names, EAP_AKA, EAP_AKA, EAP_SIM,
+ "AKA");
+ENUM_NEXT(eap_type_short_names, EAP_MSCHAPV2, EAP_MSCHAPV2, EAP_AKA,
+ "MSCHAPV2");
+ENUM_NEXT(eap_type_short_names, EAP_RADIUS, EAP_EXPERIMENTAL, EAP_MSCHAPV2,
+ "RAD",
+ "EXP",
+ "XP");
+ENUM_END(eap_type_short_names, EAP_EXPERIMENTAL);
+
+ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_SUBJECT_HASH_URL,
+ "RULE_IDENTITY",
+ "RULE_AUTH_CLASS",
+ "RULE_EAP_IDENTITY",
+ "RULE_EAP_TYPE",
+ "RULE_EAP_VENDOR",
+ "RULE_CA_CERT",
+ "RULE_IM_CERT",
+ "RULE_SUBJECT_CERT",
+ "RULE_CRL_VALIDATION",
+ "RULE_OCSP_VALIDATION",
+ "RULE_GROUP",
+ "HELPER_IM_CERT",
+ "HELPER_SUBJECT_CERT",
+ "HELPER_IM_HASH_URL",
+ "HELPER_SUBJECT_HASH_URL",
+);
+
+typedef struct private_auth_cfg_t private_auth_cfg_t;
+
+/**
+ * private data of item_set
+ */
+struct private_auth_cfg_t {
+
+ /**
+ * public functions
+ */
+ auth_cfg_t public;
+
+ /**
+ * list of entry_t
+ */
+ linked_list_t *entries;
+};
+
+typedef struct entry_t entry_t;
+
+struct entry_t {
+ /** rule type */
+ auth_rule_t type;
+ /** associated value */
+ void *value;
+};
+
+/**
+ * enumerator for auth_cfg_t.create_enumerator()
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** inner enumerator from linked_list_t */
+ enumerator_t *inner;
+ /** current entry */
+ entry_t *current;
+} entry_enumerator_t;
+
+/**
+ * enumerate function for item_enumerator_t
+ */
+static bool enumerate(entry_enumerator_t *this, auth_rule_t *type, void **value)
+{
+ entry_t *entry;
+
+ if (this->inner->enumerate(this->inner, &entry))
+ {
+ this->current = entry;
+ *type = entry->type;
+ *value = entry->value;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * destroy function for item_enumerator_t
+ */
+static void entry_enumerator_destroy(entry_enumerator_t *this)
+{
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * Implementation of auth_cfg_t.create_enumerator.
+ */
+static enumerator_t* create_enumerator(private_auth_cfg_t *this)
+{
+ entry_enumerator_t *enumerator;
+
+ enumerator = malloc_thing(entry_enumerator_t);
+ enumerator->inner = this->entries->create_enumerator(this->entries);
+ enumerator->public.enumerate = (void*)enumerate;
+ enumerator->public.destroy = (void*)entry_enumerator_destroy;
+ enumerator->current = NULL;
+ return &enumerator->public;
+}
+
+/**
+ * Destroy the value associated with an entry
+ */
+static void destroy_entry_value(entry_t *entry)
+{
+ switch (entry->type)
+ {
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_GROUP:
+ {
+ identification_t *id = (identification_t*)entry->value;
+ id->destroy(id);
+ break;
+ }
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ {
+ certificate_t *cert = (certificate_t*)entry->value;
+ cert->destroy(cert);
+ break;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ free(entry->value);
+ break;
+ }
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ break;
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.replace.
+ */
+static void replace(auth_cfg_t *this, entry_enumerator_t *enumerator,
+ auth_rule_t type, ...)
+{
+ if (enumerator->current)
+ {
+ va_list args;
+
+ va_start(args, type);
+
+ destroy_entry_value(enumerator->current);
+ enumerator->current->type = type;
+ switch (type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ /* integer type */
+ enumerator->current->value = (void*)(uintptr_t)va_arg(args, u_int);
+ break;
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_GROUP:
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ /* pointer type */
+ enumerator->current->value = va_arg(args, void*);
+ break;
+ }
+ va_end(args);
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.get.
+ */
+static void* get(private_auth_cfg_t *this, auth_rule_t type)
+{
+ enumerator_t *enumerator;
+ void *current_value, *best_value = NULL;
+ auth_rule_t current_type;
+ bool found = FALSE;
+
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &current_type, &current_value))
+ {
+ if (type == current_type)
+ {
+ if (type == AUTH_RULE_CRL_VALIDATION ||
+ type == AUTH_RULE_OCSP_VALIDATION)
+ { /* for CRL/OCSP validation, always get() the highest value */
+ if (!found || current_value > best_value)
+ {
+ best_value = current_value;
+ }
+ found = TRUE;
+ continue;
+ }
+ best_value = current_value;
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (found)
+ {
+ return best_value;
+ }
+ switch (type)
+ {
+ /* use some sane defaults if we don't find an entry */
+ case AUTH_RULE_AUTH_CLASS:
+ return (void*)AUTH_CLASS_ANY;
+ case AUTH_RULE_EAP_TYPE:
+ return (void*)EAP_NAK;
+ case AUTH_RULE_EAP_VENDOR:
+ return (void*)0;
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ return (void*)VALIDATION_FAILED;
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_GROUP:
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.add.
+ */
+static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
+{
+ entry_t *entry = malloc_thing(entry_t);
+ va_list args;
+
+ va_start(args, type);
+ entry->type = type;
+ switch (type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ /* integer type */
+ entry->value = (void*)(uintptr_t)va_arg(args, u_int);
+ break;
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_GROUP:
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ /* pointer type */
+ entry->value = va_arg(args, void*);
+ break;
+ }
+ va_end(args);
+ this->entries->insert_last(this->entries, entry);
+}
+
+/**
+ * Implementation of auth_cfg_t.complies.
+ */
+static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints,
+ bool log_error)
+{
+ enumerator_t *e1, *e2;
+ bool success = TRUE, has_group = FALSE, group_match = FALSE;
+ auth_rule_t t1, t2;
+ void *value;
+
+ e1 = constraints->create_enumerator(constraints);
+ while (e1->enumerate(e1, &t1, &value))
+ {
+ switch (t1)
+ {
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ {
+ certificate_t *c1, *c2;
+
+ c1 = (certificate_t*)value;
+
+ success = FALSE;
+ e2 = create_enumerator(this);
+ while (e2->enumerate(e2, &t2, &c2))
+ {
+ if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
+ c1->equals(c1, c2))
+ {
+ success = TRUE;
+ }
+ }
+ e2->destroy(e2);
+ if (!success && log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: peer not "
+ "authenticated by CA '%Y'.", c1->get_subject(c1));
+ }
+ break;
+ }
+ case AUTH_RULE_SUBJECT_CERT:
+ {
+ certificate_t *c1, *c2;
+
+ c1 = (certificate_t*)value;
+ c2 = get(this, AUTH_RULE_SUBJECT_CERT);
+ if (!c2 || !c1->equals(c1, c2))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: peer not "
+ "authenticated with peer cert '%Y'.",
+ c1->get_subject(c1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ {
+ cert_validation_t validated, required;
+
+ required = (uintptr_t)value;
+ validated = (uintptr_t)get(this, t1);
+ switch (required)
+ {
+ case VALIDATION_FAILED:
+ /* no constraint */
+ break;
+ case VALIDATION_SKIPPED:
+ if (validated == VALIDATION_SKIPPED)
+ {
+ break;
+ }
+ /* FALL */
+ case VALIDATION_GOOD:
+ if (validated == VALIDATION_GOOD)
+ {
+ break;
+ }
+ /* FALL */
+ default:
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: %N is %N, "
+ "but requires at least %N", auth_rule_names,
+ t1, cert_validation_names, validated,
+ cert_validation_names, required);
+ }
+ break;
+ }
+ break;
+ }
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ {
+ identification_t *id1, *id2;
+
+ id1 = (identification_t*)value;
+ id2 = get(this, t1);
+ if (!id2 || !id2->matches(id2, id1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: %sidentity '%Y'"
+ " required ", t1 == AUTH_RULE_IDENTITY ? "" :
+ "EAP ", id1);
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_AUTH_CLASS:
+ {
+ if ((uintptr_t)value != AUTH_CLASS_ANY &&
+ (uintptr_t)value != (uintptr_t)get(this, t1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint requires %N authentication, "
+ "but %N was used", auth_class_names, (uintptr_t)value,
+ auth_class_names, (uintptr_t)get(this, t1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_EAP_TYPE:
+ {
+ if ((uintptr_t)value != (uintptr_t)get(this, t1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint requires %N, "
+ "but %N was used", eap_type_names, (uintptr_t)value,
+ eap_type_names, (uintptr_t)get(this, t1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_EAP_VENDOR:
+ {
+ if ((uintptr_t)value != (uintptr_t)get(this, t1))
+ {
+ success = FALSE;
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint requires EAP vendor %d, "
+ "but %d was used", (uintptr_t)value,
+ (uintptr_t)get(this, t1));
+ }
+ }
+ break;
+ }
+ case AUTH_RULE_GROUP:
+ {
+ identification_t *id1, *id2;
+
+ /* for groups, a match of a single group is sufficient */
+ has_group = TRUE;
+ id1 = (identification_t*)value;
+ e2 = create_enumerator(this);
+ while (e2->enumerate(e2, &t2, &id2))
+ {
+ if (t2 == AUTH_RULE_GROUP && id2->matches(id2, id1))
+ {
+ group_match = TRUE;
+ }
+ }
+ e2->destroy(e2);
+ break;
+ }
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ /* skip helpers */
+ continue;
+ }
+ if (!success)
+ {
+ break;
+ }
+ }
+ e1->destroy(e1);
+
+ if (has_group && !group_match)
+ {
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: group membership required");
+ }
+ return FALSE;
+ }
+ return success;
+}
+
+/**
+ * Implementation of auth_cfg_t.merge.
+ */
+static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy)
+{
+ if (!other)
+ { /* nothing to merge */
+ return;
+ }
+ if (copy)
+ {
+ enumerator_t *enumerator;
+ auth_rule_t type;
+ void *value;
+
+ enumerator = create_enumerator(other);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ switch (type)
+ {
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ {
+ certificate_t *cert = (certificate_t*)value;
+
+ add(this, type, cert->get_ref(cert));
+ break;
+ }
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ {
+ add(this, type, (uintptr_t)value);
+ break;
+ }
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_GROUP:
+ {
+ identification_t *id = (identification_t*)value;
+
+ add(this, type, id->clone(id));
+ break;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ add(this, type, strdup((char*)value));
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ else
+ {
+ entry_t *entry;
+
+ while (other->entries->remove_first(other->entries,
+ (void**)&entry) == SUCCESS)
+ {
+ this->entries->insert_last(this->entries, entry);
+ }
+ }
+}
+
+/**
+ * Implementation of auth_cfg_t.equals.
+ */
+static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
+{
+ enumerator_t *e1, *e2;
+ entry_t *i1, *i2;
+ bool equal = TRUE, found;
+
+ if (this->entries->get_count(this->entries) !=
+ other->entries->get_count(other->entries))
+ {
+ return FALSE;
+ }
+ e1 = this->entries->create_enumerator(this->entries);
+ while (e1->enumerate(e1, &i1))
+ {
+ found = FALSE;
+ e2 = other->entries->create_enumerator(other->entries);
+ while (e2->enumerate(e2, &i2))
+ {
+ if (i1->type == i2->type)
+ {
+ switch (i1->type)
+ {
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ {
+ if (i1->value == i2->value)
+ {
+ found = TRUE;
+ break;
+ }
+ continue;
+ }
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ {
+ certificate_t *c1, *c2;
+
+ c1 = (certificate_t*)i1->value;
+ c2 = (certificate_t*)i2->value;
+
+ if (c1->equals(c1, c2))
+ {
+ found = TRUE;
+ break;
+ }
+ continue;
+ }
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_GROUP:
+ {
+ identification_t *id1, *id2;
+
+ id1 = (identification_t*)i1->value;
+ id2 = (identification_t*)i2->value;
+
+ if (id1->equals(id1, id2))
+ {
+ found = TRUE;
+ break;
+ }
+ continue;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ if (streq(i1->value, i2->value))
+ {
+ found = TRUE;
+ break;
+ }
+ continue;
+ }
+ }
+ break;
+ }
+ }
+ e2->destroy(e2);
+ if (!found)
+ {
+ equal = FALSE;
+ break;
+ }
+ }
+ e1->destroy(e1);
+ return equal;
+}
+
+/**
+ * Implementation of auth_cfg_t.purge
+ */
+static void purge(private_auth_cfg_t *this, bool keep_ca)
+{
+ entry_t *entry;
+ linked_list_t *cas;
+
+ cas = linked_list_create();
+ while (this->entries->remove_last(this->entries, (void**)&entry) == SUCCESS)
+ {
+ if (keep_ca && entry->type == AUTH_RULE_CA_CERT)
+ {
+ cas->insert_first(cas, entry);
+ }
+ else
+ {
+ destroy_entry_value(entry);
+ free(entry);
+ }
+ }
+ while (cas->remove_last(cas, (void**)&entry) == SUCCESS)
+ {
+ this->entries->insert_first(this->entries, entry);
+ }
+ cas->destroy(cas);
+}
+
+/**
+ * Implementation of auth_cfg_t.clone
+ */
+static auth_cfg_t* clone_(private_auth_cfg_t *this)
+{
+ enumerator_t *enumerator;
+ auth_cfg_t *clone;
+ entry_t *entry;
+
+ clone = auth_cfg_create();
+ enumerator = this->entries->create_enumerator(this->entries);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ switch (entry->type)
+ {
+ case AUTH_RULE_IDENTITY:
+ case AUTH_RULE_EAP_IDENTITY:
+ case AUTH_RULE_GROUP:
+ {
+ identification_t *id = (identification_t*)entry->value;
+ clone->add(clone, entry->type, id->clone(id));
+ break;
+ }
+ case AUTH_RULE_CA_CERT:
+ case AUTH_RULE_IM_CERT:
+ case AUTH_RULE_SUBJECT_CERT:
+ case AUTH_HELPER_IM_CERT:
+ case AUTH_HELPER_SUBJECT_CERT:
+ {
+ certificate_t *cert = (certificate_t*)entry->value;
+ clone->add(clone, entry->type, cert->get_ref(cert));
+ break;
+ }
+ case AUTH_HELPER_IM_HASH_URL:
+ case AUTH_HELPER_SUBJECT_HASH_URL:
+ {
+ clone->add(clone, entry->type, strdup(entry->value));
+ break;
+ }
+ case AUTH_RULE_AUTH_CLASS:
+ case AUTH_RULE_EAP_TYPE:
+ case AUTH_RULE_EAP_VENDOR:
+ case AUTH_RULE_CRL_VALIDATION:
+ case AUTH_RULE_OCSP_VALIDATION:
+ clone->add(clone, entry->type, (uintptr_t)entry->value);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return clone;
+}
+
+/**
+ * Implementation of auth_cfg_t.destroy
+ */
+static void destroy(private_auth_cfg_t *this)
+{
+ purge(this, FALSE);
+ this->entries->destroy(this->entries);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+auth_cfg_t *auth_cfg_create()
+{
+ private_auth_cfg_t *this = malloc_thing(private_auth_cfg_t);
+
+ this->public.add = (void(*)(auth_cfg_t*, auth_rule_t type, ...))add;
+ this->public.get = (void*(*)(auth_cfg_t*, auth_rule_t type))get;
+ this->public.create_enumerator = (enumerator_t*(*)(auth_cfg_t*))create_enumerator;
+ this->public.replace = (void(*)(auth_cfg_t*,enumerator_t*,auth_rule_t,...))replace;
+ this->public.complies = (bool(*)(auth_cfg_t*, auth_cfg_t *,bool))complies;
+ this->public.merge = (void(*)(auth_cfg_t*, auth_cfg_t *other,bool))merge;
+ this->public.purge = (void(*)(auth_cfg_t*,bool))purge;
+ this->public.equals = (bool(*)(auth_cfg_t*, auth_cfg_t *other))equals;
+ this->public.clone = (auth_cfg_t*(*)(auth_cfg_t*))clone_;
+ this->public.destroy = (void(*)(auth_cfg_t*))destroy;
+
+ this->entries = linked_list_create();
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/credentials/auth_cfg.h b/src/libstrongswan/credentials/auth_cfg.h
new file mode 100644
index 000000000..713e16372
--- /dev/null
+++ b/src/libstrongswan/credentials/auth_cfg.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2007-2009 Martin Willi
+ * Copyright (C) 2008 Tobias Brunner
+ * 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 auth_cfg auth_cfg
+ * @{ @ingroup credentials
+ */
+
+#ifndef AUTH_CFG_H_
+#define AUTH_CFG_H_
+
+#include <utils/enumerator.h>
+
+typedef struct auth_cfg_t auth_cfg_t;
+typedef enum auth_rule_t auth_rule_t;
+typedef enum auth_class_t auth_class_t;
+typedef enum eap_type_t eap_type_t;
+
+/**
+ * Class of authentication to use. This is different to auth_method_t in that
+ * it does not specify a method, but a class of acceptable methods. The found
+ * certificate finally dictates wich method is used.
+ */
+enum auth_class_t {
+ /** any class acceptable */
+ AUTH_CLASS_ANY = 0,
+ /** authentication using public keys (RSA, ECDSA) */
+ AUTH_CLASS_PUBKEY = 1,
+ /** authentication using a pre-shared secrets */
+ AUTH_CLASS_PSK = 2,
+ /** authentication using EAP */
+ AUTH_CLASS_EAP = 3,
+};
+
+/**
+ * enum strings for auth_class_t
+ */
+extern enum_name_t *auth_class_names;
+
+/**
+ * EAP types, defines the EAP method implementation
+ */
+enum eap_type_t {
+ EAP_IDENTITY = 1,
+ EAP_NOTIFICATION = 2,
+ EAP_NAK = 3,
+ EAP_MD5 = 4,
+ EAP_OTP = 5,
+ EAP_GTC = 6,
+ EAP_SIM = 18,
+ EAP_AKA = 23,
+ EAP_MSCHAPV2 = 26,
+ /** not a method, but an implementation providing different methods */
+ EAP_RADIUS = 253,
+ EAP_EXPANDED = 254,
+ EAP_EXPERIMENTAL = 255,
+};
+
+/**
+ * enum names for eap_type_t.
+ */
+extern enum_name_t *eap_type_names;
+
+/**
+ * short string enum names for eap_type_t.
+ */
+extern enum_name_t *eap_type_short_names;
+
+/**
+ * Authentication config to use during authentication process.
+ *
+ * Each authentication config contains a set of rules. These rule-sets are used
+ * in two ways:
+ * - For configs specifying local authentication behavior, the rules define
+ * which authentication method in which way.
+ * - For configs specifying remote peer authentication, the rules define
+ * constraints the peer has to fullfill.
+ *
+ * Additionally to the rules, there is a set of helper items. These are used
+ * to transport credentials during the authentication process.
+ */
+enum auth_rule_t {
+
+ /** identity to use for IKEv2 authentication exchange, identification_t* */
+ AUTH_RULE_IDENTITY,
+ /** authentication class, auth_class_t */
+ AUTH_RULE_AUTH_CLASS,
+ /** EAP identity to use within EAP-Identity exchange, identification_t* */
+ AUTH_RULE_EAP_IDENTITY,
+ /** EAP type to propose for peer authentication, eap_type_t */
+ AUTH_RULE_EAP_TYPE,
+ /** EAP vendor for vendor specific type, u_int32_t */
+ AUTH_RULE_EAP_VENDOR,
+ /** certificate authority, certificate_t* */
+ AUTH_RULE_CA_CERT,
+ /** intermediate certificate in trustchain, certificate_t* */
+ AUTH_RULE_IM_CERT,
+ /** subject certificate, certificate_t* */
+ AUTH_RULE_SUBJECT_CERT,
+ /** result of a CRL validation, cert_validation_t */
+ AUTH_RULE_CRL_VALIDATION,
+ /** result of a OCSP validation, cert_validation_t */
+ AUTH_RULE_OCSP_VALIDATION,
+ /** subject is member of a group, identification_t*
+ * The group membership constraint is fulfilled if the subject is member of
+ * one group defined in the constraints. */
+ AUTH_RULE_GROUP,
+
+ /** intermediate certificate, certificate_t* */
+ AUTH_HELPER_IM_CERT,
+ /** subject certificate, certificate_t* */
+ AUTH_HELPER_SUBJECT_CERT,
+ /** Hash and URL of a intermediate certificate, char* */
+ AUTH_HELPER_IM_HASH_URL,
+ /** Hash and URL of a end-entity certificate, char* */
+ AUTH_HELPER_SUBJECT_HASH_URL,
+};
+
+/**
+ * enum name for auth_rule_t.
+ */
+extern enum_name_t *auth_rule_names;
+
+/**
+ * Authentication/Authorization round.
+ *
+ * RFC4739 defines multiple authentication rounds. This class defines such
+ * a round from a configuration perspective, either for the local or the remote
+ * peer. Local config are called "rulesets", as they define how we authenticate.
+ * Remote peer configs are called "constraits", they define what is needed to
+ * complete the authentication round successfully.
+ *
+ * @verbatim
+
+ [Repeat for each configuration]
+ +--------------------------------------------------+
+ | |
+ | |
+ | +----------+ IKE_AUTH +--------- + |
+ | | config | -----------> | | |
+ | | ruleset | | | |
+ | +----------+ [ <----------- ] | | |
+ | [ optional EAP ] | Peer | |
+ | +----------+ [ -----------> ] | | |
+ | | config | | | |
+ | | constr. | <----------- | | |
+ | +----------+ IKE_AUTH +--------- + |
+ | |
+ | |
+ +--------------------------------------------------+
+
+ @endverbatim
+ *
+ * Values for each items are either pointers (casted to void*) or short
+ * integers (use uintptr_t cast).
+ */
+struct auth_cfg_t {
+
+ /**
+ * Add an rule to the set.
+ *
+ * @param rule rule type
+ * @param ... associated value to rule
+ */
+ void (*add)(auth_cfg_t *this, auth_rule_t rule, ...);
+
+ /**
+ * Get an rule value.
+ *
+ * @param rule rule type
+ * @return bool if item has been found
+ */
+ void* (*get)(auth_cfg_t *this, auth_rule_t rule);
+
+ /**
+ * Create an enumerator over added rules.
+ *
+ * @return enumerator over (auth_rule_t, union{void*,uintpr_t})
+ */
+ enumerator_t* (*create_enumerator)(auth_cfg_t *this);
+
+ /**
+ * Replace an rule at enumerator position.
+ *
+ * @param pos enumerator position position
+ * @param rule rule type
+ * @param ... associated value to rule
+ */
+ void (*replace)(auth_cfg_t *this, enumerator_t *pos,
+ auth_rule_t rule, ...);
+
+ /**
+ * Check if a used config fulfills a set of configured constraints.
+ *
+ * @param constraints required authorization rules
+ * @param log_error wheter to log compliance errors
+ * @return TRUE if this complies with constraints
+ */
+ bool (*complies)(auth_cfg_t *this, auth_cfg_t *constraints, bool log_error);
+
+ /**
+ * Merge items from other into this.
+ *
+ * @param other items to read for merge
+ * @param copy TRUE to copy items, FALSE to move them
+ */
+ void (*merge)(auth_cfg_t *this, auth_cfg_t *other, bool copy);
+
+ /**
+ * Purge all rules in a config.
+ *
+ * @param keep_ca wheter to keep AUTH_RULE_CA_CERT entries
+ */
+ void (*purge)(auth_cfg_t *this, bool keep_ca);
+
+ /**
+ * Check two configs for equality.
+ *
+ * @param other other config to compaire against this
+ * @return TRUE if auth infos identical
+ */
+ bool (*equals)(auth_cfg_t *this, auth_cfg_t *other);
+
+ /**
+ * Clone a authentication config, including all rules.
+ *
+ * @return cloned configuration
+ */
+ auth_cfg_t* (*clone)(auth_cfg_t *this);
+
+ /**
+ * Destroy a config with all associated rules/values.
+ */
+ void (*destroy)(auth_cfg_t *this);
+};
+
+/**
+ * Create a authentication config.
+ */
+auth_cfg_t *auth_cfg_create();
+
+#endif /** AUTH_CFG_H_ @}*/
diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c
index 8be1c1576..cfb708e33 100644
--- a/src/libstrongswan/credentials/builder.c
+++ b/src/libstrongswan/credentials/builder.c
@@ -44,6 +44,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
"BUILD_OCSP_ACCESS_LOCATIONS",
"BUILD_PATHLEN",
"BUILD_X509_FLAG",
+ "BUILD_REVOKED_ENUMERATOR",
"BUILD_SMARTCARD_KEYID",
"BUILD_SMARTCARD_PIN",
"BUILD_RSA_MODULUS",
diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h
index 62a6ffaaf..ffb09f72a 100644
--- a/src/libstrongswan/credentials/builder.h
+++ b/src/libstrongswan/credentials/builder.h
@@ -101,6 +101,8 @@ enum builder_part_t {
BUILD_PATHLEN,
/** enforce an additional X509 flag, x509_flag_t */
BUILD_X509_FLAG,
+ /** enumerator_t over (chunk_t serial, time_t date, crl_reason_t reason) */
+ BUILD_REVOKED_ENUMERATOR,
/** key ID of a key on a smartcard, null terminated char* ([slot:]keyid) */
BUILD_SMARTCARD_KEYID,
/** pin to access a key on a smartcard, null terminated char* */
diff --git a/src/libstrongswan/credentials/cert_validator.h b/src/libstrongswan/credentials/cert_validator.h
new file mode 100644
index 000000000..1e67c23ab
--- /dev/null
+++ b/src/libstrongswan/credentials/cert_validator.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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 cert_validator cert_validator
+ * @{ @ingroup credentials
+ */
+
+#ifndef CERT_VALIDATOR_H_
+#define CERT_VALIDATOR_H_
+
+typedef struct cert_validator_t cert_validator_t;
+
+#include <library.h>
+
+/**
+ * Certificate validator interface.
+ *
+ * A certificate validator checks constraints or revocation in a certificate
+ * or its issuing CA certificate. The interface allows plugins to do
+ * revocation checking or similar tasks.
+ */
+struct cert_validator_t {
+
+ /**
+ * Validate a subject certificate in relation to its issuer.
+ *
+ * @param subject subject certificate to check
+ * @param issuer issuer of subject
+ * @param online wheter to do online revocation checking
+ * @param pathlen the current length of the path up to the root CA
+ * @param auth container for resulting authentication info
+ */
+ bool (*validate)(cert_validator_t *this, certificate_t *subject,
+ certificate_t *issuer, bool online, int pathlen,
+ auth_cfg_t *auth);
+};
+
+#endif /** CERT_VALIDATOR_H_ @}*/
diff --git a/src/libstrongswan/credentials/certificates/certificate.c b/src/libstrongswan/credentials/certificates/certificate.c
index 156d12358..661b69e36 100644
--- a/src/libstrongswan/credentials/certificates/certificate.c
+++ b/src/libstrongswan/credentials/certificates/certificate.c
@@ -15,6 +15,7 @@
#include "certificate.h"
+#include <debug.h>
#include <credentials/certificates/x509.h>
ENUM(certificate_type_names, CERT_ANY, CERT_PLUTO_CRL,
@@ -40,3 +41,24 @@ ENUM(cert_validation_names, VALIDATION_GOOD, VALIDATION_REVOKED,
"REVOKED",
);
+/**
+ * See header
+ */
+bool certificate_is_newer(certificate_t *this, certificate_t *other)
+{
+ time_t this_update, that_update;
+ char *type = "certificate";
+ bool newer;
+
+ if (this->get_type(this) == CERT_X509_CRL)
+ {
+ type = "crl";
+ }
+ this->get_validity(this, NULL, &this_update, NULL);
+ other->get_validity(other, NULL, &that_update, NULL);
+ newer = this_update > that_update;
+ DBG1(DBG_LIB, " %s from %T is %s - existing %s from %T %s",
+ type, &this_update, FALSE, newer ? "newer" : "not newer",
+ type, &that_update, FALSE, newer ? "replaced" : "retained");
+ return newer;
+}
diff --git a/src/libstrongswan/credentials/certificates/certificate.h b/src/libstrongswan/credentials/certificates/certificate.h
index a4f9aa3e0..43bfe3dc1 100644
--- a/src/libstrongswan/credentials/certificates/certificate.h
+++ b/src/libstrongswan/credentials/certificates/certificate.h
@@ -28,6 +28,7 @@ typedef enum cert_validation_t cert_validation_t;
#include <library.h>
#include <utils/identification.h>
#include <credentials/keys/public_key.h>
+#include <credentials/cred_encoding.h>
/**
* Kind of a certificate_t
@@ -163,18 +164,14 @@ struct certificate_t {
time_t *not_before, time_t *not_after);
/**
- * Is this newer than that?
+ * Get the certificate in an encoded form as a chunk.
*
- * @return TRUE if newer, FALSE otherwise
+ * @param type type of the encoding, one of CERT_*
+ * @param encoding encoding of the key, allocated
+ * @return TRUE if encoding supported
*/
- bool (*is_newer)(certificate_t *this, certificate_t *that);
-
- /**
- * Get the certificate in an encoded form.
- *
- * @return allocated chunk of encoded cert
- */
- chunk_t (*get_encoding)(certificate_t *this);
+ bool (*get_encoding)(certificate_t *this, cred_encoding_type_t type,
+ chunk_t *encoding);
/**
* Check if two certificates are equal.
@@ -197,4 +194,13 @@ struct certificate_t {
void (*destroy)(certificate_t *this);
};
+/**
+ * Generic check if a given certificate is newer than another.
+ *
+ * @param this first certificate to check
+ * @param other second certificate
+ * @return TRUE if this newer than other
+ */
+bool certificate_is_newer(certificate_t *this, certificate_t *other);
+
#endif /** CERTIFICATE_H_ @}*/
diff --git a/src/libstrongswan/credentials/certificates/crl.c b/src/libstrongswan/credentials/certificates/crl.c
index 085ad16cc..69bd80b84 100644
--- a/src/libstrongswan/credentials/certificates/crl.c
+++ b/src/libstrongswan/credentials/certificates/crl.c
@@ -16,6 +16,8 @@
#include "crl.h"
+#include <debug.h>
+
ENUM(crl_reason_names, CRL_REASON_UNSPECIFIED, CRL_REASON_REMOVE_FROM_CRL,
"unspecified",
"key compromise",
@@ -27,3 +29,29 @@ ENUM(crl_reason_names, CRL_REASON_UNSPECIFIED, CRL_REASON_REMOVE_FROM_CRL,
"reason #7",
"remove from crl",
);
+
+/**
+ * Check if this CRL is newer
+ */
+bool crl_is_newer(crl_t *this, crl_t *other)
+{
+ chunk_t this_num, other_num;
+ bool newer;
+
+ this_num = this->get_serial(this);
+ other_num = other->get_serial(other);
+
+ /* compare crlNumbers if available - otherwise use generic cert compare */
+ if (this_num.ptr != NULL && other_num.ptr != NULL)
+ {
+ newer = chunk_compare(this_num, other_num) > 0;
+ DBG1(DBG_LIB, " crl #%#B is %s - existing crl #%#B %s",
+ &this_num, newer ? "newer" : "not newer",
+ &other_num, newer ? "replaced" : "retained");
+ }
+ else
+ {
+ newer = certificate_is_newer(&this->certificate, &other->certificate);
+ }
+ return newer;
+}
diff --git a/src/libstrongswan/credentials/certificates/crl.h b/src/libstrongswan/credentials/certificates/crl.h
index 4b612390c..9425311fb 100644
--- a/src/libstrongswan/credentials/certificates/crl.h
+++ b/src/libstrongswan/credentials/certificates/crl.h
@@ -80,7 +80,15 @@ struct crl_t {
* @return enumerator over revoked certificates.
*/
enumerator_t* (*create_enumerator)(crl_t *this);
-
};
+/**
+ * Generic check if a given CRL is newer than another.
+ *
+ * @param this first CRL to check
+ * @param other second CRL
+ * @return TRUE if this newer than other
+ */
+bool crl_is_newer(crl_t *this, crl_t *other);
+
#endif /** CRL_H_ @}*/
diff --git a/src/libstrongswan/credentials/certificates/x509.h b/src/libstrongswan/credentials/certificates/x509.h
index 172bd9696..6e0a5002a 100644
--- a/src/libstrongswan/credentials/certificates/x509.h
+++ b/src/libstrongswan/credentials/certificates/x509.h
@@ -25,7 +25,6 @@
#include <credentials/certificates/certificate.h>
#define X509_NO_PATH_LEN_CONSTRAINT -1
-#define X509_MAX_PATH_LEN 7
typedef struct x509_t x509_t;
typedef enum x509_flag_t x509_flag_t;
diff --git a/src/libstrongswan/credentials/keys/key_encoding.c b/src/libstrongswan/credentials/cred_encoding.c
index 89b25226c..edd76205b 100644
--- a/src/libstrongswan/credentials/keys/key_encoding.c
+++ b/src/libstrongswan/credentials/cred_encoding.c
@@ -13,7 +13,7 @@
* for more details.
*/
-#include "key_encoding.h"
+#include "cred_encoding.h"
#include <stdint.h>
@@ -21,25 +21,25 @@
#include <utils/hashtable.h>
#include <threading/rwlock.h>
-typedef struct private_key_encoding_t private_key_encoding_t;
+typedef struct private_cred_encoding_t private_cred_encoding_t;
/**
- * Private data of an key_encoding_t object.
+ * Private data of an cred_encoding_t object.
*/
-struct private_key_encoding_t {
+struct private_cred_encoding_t {
/**
- * Public key_encoding_t interface.
+ * Public cred_encoding_t interface.
*/
- key_encoding_t public;
+ cred_encoding_t public;
/**
* cached encodings, a table for each encoding_type_t, containing chunk_t*
*/
- hashtable_t *cache[KEY_ENCODING_MAX];
+ hashtable_t *cache[CRED_ENCODING_MAX];
/**
- * Registered encoding fuctions, key_encoder_t
+ * Registered encoding fuctions, cred_encoder_t
*/
linked_list_t *encoders;
@@ -52,7 +52,7 @@ struct private_key_encoding_t {
/**
* See header.
*/
-bool key_encoding_args(va_list args, ...)
+bool cred_encoding_args(va_list args, ...)
{
va_list parts, copy;
bool failed = FALSE;
@@ -61,12 +61,12 @@ bool key_encoding_args(va_list args, ...)
while (!failed)
{
- key_encoding_part_t current, target;
+ cred_encoding_part_t current, target;
chunk_t *out, data;
/* get the part we are looking for */
- target = va_arg(parts, key_encoding_part_t);
- if (target == KEY_PART_END)
+ target = va_arg(parts, cred_encoding_part_t);
+ if (target == CRED_PART_END)
{
break;
}
@@ -75,8 +75,8 @@ bool key_encoding_args(va_list args, ...)
va_copy(copy, args);
while (!failed)
{
- current = va_arg(copy, key_encoding_part_t);
- if (current == KEY_PART_END)
+ current = va_arg(copy, cred_encoding_part_t);
+ if (current == CRED_PART_END)
{
failed = TRUE;
break;
@@ -111,14 +111,14 @@ static bool equals(void *key1, void *key2)
}
/**
- * Implementation of key_encoding_t.get_cache
+ * Implementation of cred_encoding_t.get_cache
*/
-static bool get_cache(private_key_encoding_t *this, key_encoding_type_t type,
+static bool get_cache(private_cred_encoding_t *this, cred_encoding_type_t type,
void *cache, chunk_t *encoding)
{
chunk_t *chunk;
- if (type >= KEY_ENCODING_MAX || type < 0)
+ if (type >= CRED_ENCODING_MAX || type < 0)
{
return FALSE;
}
@@ -133,18 +133,18 @@ static bool get_cache(private_key_encoding_t *this, key_encoding_type_t type,
}
/**
- * Implementation of key_encoding_t.encode
+ * Implementation of cred_encoding_t.encode
*/
-static bool encode(private_key_encoding_t *this, key_encoding_type_t type,
+static bool encode(private_cred_encoding_t *this, cred_encoding_type_t type,
void *cache, chunk_t *encoding, ...)
{
enumerator_t *enumerator;
va_list args, copy;
- key_encoder_t encode;
+ cred_encoder_t encode;
bool success = FALSE;
chunk_t *chunk;
- if (type >= KEY_ENCODING_MAX || type < 0)
+ if (type >= CRED_ENCODING_MAX || type < 0)
{
return FALSE;
}
@@ -168,32 +168,33 @@ static bool encode(private_key_encoding_t *this, key_encoding_type_t type,
va_end(copy);
if (success)
{
- if (cache)
- {
- chunk = malloc_thing(chunk_t);
- *chunk = *encoding;
- this->lock->unlock(this->lock);
- this->lock->write_lock(this->lock);
- this->cache[type]->put(this->cache[type], cache, chunk);
- }
break;
}
}
enumerator->destroy(enumerator);
- va_end(args);
this->lock->unlock(this->lock);
+ va_end(args);
+
+ if (success && cache)
+ {
+ chunk = malloc_thing(chunk_t);
+ *chunk = *encoding;
+ this->lock->write_lock(this->lock);
+ this->cache[type]->put(this->cache[type], cache, chunk);
+ this->lock->unlock(this->lock);
+ }
return success;
}
/**
- * Implementation of key_encoding_t.cache
+ * Implementation of cred_encoding_t.cache
*/
-static void cache(private_key_encoding_t *this, key_encoding_type_t type,
+static void cache(private_cred_encoding_t *this, cred_encoding_type_t type,
void *cache, chunk_t encoding)
{
chunk_t *chunk;
- if (type >= KEY_ENCODING_MAX || type < 0)
+ if (type >= CRED_ENCODING_MAX || type < 0)
{
return free(encoding.ptr);
}
@@ -211,15 +212,15 @@ static void cache(private_key_encoding_t *this, key_encoding_type_t type,
}
/**
- * Implementation of key_encoding_t.clear_cache
+ * Implementation of cred_encoding_t.clear_cache
*/
-static void clear_cache(private_key_encoding_t *this, void *cache)
+static void clear_cache(private_cred_encoding_t *this, void *cache)
{
- key_encoding_type_t type;
+ cred_encoding_type_t type;
chunk_t *chunk;
this->lock->write_lock(this->lock);
- for (type = 0; type < KEY_ENCODING_MAX; type++)
+ for (type = 0; type < CRED_ENCODING_MAX; type++)
{
chunk = this->cache[type]->remove(this->cache[type], cache);
if (chunk)
@@ -232,9 +233,9 @@ static void clear_cache(private_key_encoding_t *this, void *cache)
}
/**
- * Implementation of key_encoding_t.add_encoder
+ * Implementation of cred_encoding_t.add_encoder
*/
-static void add_encoder(private_key_encoding_t *this, key_encoder_t encoder)
+static void add_encoder(private_cred_encoding_t *this, cred_encoder_t encoder)
{
this->lock->write_lock(this->lock);
this->encoders->insert_last(this->encoders, encoder);
@@ -242,9 +243,9 @@ static void add_encoder(private_key_encoding_t *this, key_encoder_t encoder)
}
/**
- * Implementation of key_encoding_t.remove_encoder
+ * Implementation of cred_encoding_t.remove_encoder
*/
-static void remove_encoder(private_key_encoding_t *this, key_encoder_t encoder)
+static void remove_encoder(private_cred_encoding_t *this, cred_encoder_t encoder)
{
this->lock->write_lock(this->lock);
this->encoders->remove(this->encoders, encoder, NULL);
@@ -252,18 +253,18 @@ static void remove_encoder(private_key_encoding_t *this, key_encoder_t encoder)
}
/**
- * Implementation of key_encoder_t.destroy.
+ * Implementation of cred_encoder_t.destroy.
*/
-static void destroy(private_key_encoding_t *this)
+static void destroy(private_cred_encoding_t *this)
{
- key_encoding_type_t type;
+ cred_encoding_type_t type;
- for (type = 0; type < KEY_ENCODING_MAX; type++)
+ for (type = 0; type < CRED_ENCODING_MAX; type++)
{
- /* We explicitly do not free remaining encodings. All keys should
+ /* We explicitly do not free remaining encodings. All creds should
* have gone now, and they are responsible for cleaning out their
* cache entries. Not flushing here allows the leak detective to
- * complain if a key did not flush cached encodings. */
+ * complain if a credential did not flush cached encodings. */
this->cache[type]->destroy(this->cache[type]);
}
this->encoders->destroy(this->encoders);
@@ -274,20 +275,20 @@ static void destroy(private_key_encoding_t *this)
/**
* See header
*/
-key_encoding_t *key_encoding_create()
+cred_encoding_t *cred_encoding_create()
{
- private_key_encoding_t *this = malloc_thing(private_key_encoding_t);
- key_encoding_type_t type;
-
- this->public.encode = (bool(*)(key_encoding_t*, key_encoding_type_t type, void *cache, chunk_t *encoding, ...))encode;
- this->public.get_cache = (bool(*)(key_encoding_t*, key_encoding_type_t type, void *cache, chunk_t *encoding))get_cache;
- this->public.cache = (void(*)(key_encoding_t*, key_encoding_type_t type, void *cache, chunk_t encoding))cache;
- this->public.clear_cache = (void(*)(key_encoding_t*, void *cache))clear_cache;
- this->public.add_encoder = (void(*)(key_encoding_t*, key_encoder_t encoder))add_encoder;
- this->public.remove_encoder = (void(*)(key_encoding_t*, key_encoder_t encoder))remove_encoder;
- this->public.destroy = (void(*)(key_encoding_t*))destroy;
-
- for (type = 0; type < KEY_ENCODING_MAX; type++)
+ private_cred_encoding_t *this = malloc_thing(private_cred_encoding_t);
+ cred_encoding_type_t type;
+
+ this->public.encode = (bool(*)(cred_encoding_t*, cred_encoding_type_t type, void *cache, chunk_t *encoding, ...))encode;
+ this->public.get_cache = (bool(*)(cred_encoding_t*, cred_encoding_type_t type, void *cache, chunk_t *encoding))get_cache;
+ this->public.cache = (void(*)(cred_encoding_t*, cred_encoding_type_t type, void *cache, chunk_t encoding))cache;
+ this->public.clear_cache = (void(*)(cred_encoding_t*, void *cache))clear_cache;
+ this->public.add_encoder = (void(*)(cred_encoding_t*, cred_encoder_t encoder))add_encoder;
+ this->public.remove_encoder = (void(*)(cred_encoding_t*, cred_encoder_t encoder))remove_encoder;
+ this->public.destroy = (void(*)(cred_encoding_t*))destroy;
+
+ for (type = 0; type < CRED_ENCODING_MAX; type++)
{
this->cache[type] = hashtable_create(hash, equals, 8);
}
diff --git a/src/libstrongswan/credentials/cred_encoding.h b/src/libstrongswan/credentials/cred_encoding.h
new file mode 100644
index 000000000..e2d69691e
--- /dev/null
+++ b/src/libstrongswan/credentials/cred_encoding.h
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2009 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 cred_encoding cred_encoding
+ * @{ @ingroup credentials
+ */
+
+#ifndef CRED_ENCODING_H_
+#define CRED_ENCODING_H_
+
+typedef struct cred_encoding_t cred_encoding_t;
+typedef enum cred_encoding_type_t cred_encoding_type_t;
+typedef enum cred_encoding_part_t cred_encoding_part_t;
+
+#include <library.h>
+
+/**
+ * Credential encoder function implementing encoding/fingerprinting.
+ *
+ * The variable argument list takes cred_encoding_part_t, followed by part
+ * specific arguments, terminated by KEY_PART_END.
+ *
+ * @param type format to encode the credential to
+ * @param args list of (cred_encoding_part_t, data)
+ * @param encoding encoding result, allocated
+ * @return TRUE if encoding successful
+ */
+typedef bool (*cred_encoder_t)(cred_encoding_type_t type, chunk_t *encoding,
+ va_list args);
+
+/**
+ * Helper function for cred_encoder_t implementations to parse argument list.
+ *
+ * Credential encoder functions get a variable argument list to parse. To
+ * simplify the job, this function reads the arguments and returns chunks for
+ * each part.
+ * The argument list of this function takes a cred_encoding_part_t, followed
+ * by a data pointer receiving the value, terminated by CRED_PART_END.
+ *
+ * @param args argument list passed to credential encoder function
+ * @param ... list of (cred_encoding_part_t, data*)
+ * @return TRUE if all parts found, FALSE otherwise
+ */
+bool cred_encoding_args(va_list args, ...);
+
+/**
+ * Encoding type of a fingerprint/credential.
+ *
+ * Fingerprints have have the KEYID_*, public keys the PUBKEY_* and
+ * private keys the PRIVKEY_* prefix.
+ */
+enum cred_encoding_type_t {
+ /** SHA1 fingerprint over subjectPublicKeyInfo */
+ KEYID_PUBKEY_INFO_SHA1 = 0,
+ /** SHA1 fingerprint over subjectPublicKey */
+ KEYID_PUBKEY_SHA1,
+ /** PGPv3 fingerprint */
+ KEYID_PGPV3,
+ /** PGPv4 fingerprint */
+ KEYID_PGPV4,
+
+ KEYID_MAX,
+
+ /** PKCS#1 and similar ASN.1 key encoding */
+ PUBKEY_ASN1_DER,
+ PRIVKEY_ASN1_DER,
+ /** subjectPublicKeyInfo encoding */
+ PUBKEY_SPKI_ASN1_DER,
+ /** PEM encoded PKCS#1 key */
+ PUBKEY_PEM,
+ PRIVKEY_PEM,
+ /** PGP key encoding */
+ PUBKEY_PGP,
+ PRIVKEY_PGP,
+
+ /** ASN.1 DER encoded certificate */
+ CERT_ASN1_DER,
+ /** PEM encoded certificate */
+ CERT_PEM,
+ /** PGP Packet encoded certificate */
+ CERT_PGP_PKT,
+
+ CRED_ENCODING_MAX,
+};
+
+/**
+ * Parts of a credential to encode.
+ */
+enum cred_encoding_part_t {
+ /** modulus of a RSA key, n */
+ CRED_PART_RSA_MODULUS,
+ /** public exponent of a RSA key, e */
+ CRED_PART_RSA_PUB_EXP,
+ /** private exponent of a RSA key, d */
+ CRED_PART_RSA_PRIV_EXP,
+ /** prime1 a RSA key, p */
+ CRED_PART_RSA_PRIME1,
+ /** prime2 a RSA key, q */
+ CRED_PART_RSA_PRIME2,
+ /** exponent1 a RSA key, exp1 */
+ CRED_PART_RSA_EXP1,
+ /** exponent1 a RSA key, exp2 */
+ CRED_PART_RSA_EXP2,
+ /** coefficient of RSA key, coeff */
+ CRED_PART_RSA_COEFF,
+ /** a DER encoded RSA public key */
+ CRED_PART_RSA_PUB_ASN1_DER,
+ /** a DER encoded RSA private key */
+ CRED_PART_RSA_PRIV_ASN1_DER,
+ /** a DER encoded ECDSA public key */
+ CRED_PART_ECDSA_PUB_ASN1_DER,
+ /** a DER encoded ECDSA private key */
+ CRED_PART_ECDSA_PRIV_ASN1_DER,
+ /** a DER encoded X509 certificate */
+ CRED_PART_X509_ASN1_DER,
+ /** a DER encoded X509 CRL */
+ CRED_PART_X509_CRL_ASN1_DER,
+ /** a DER encoded X509 OCSP request */
+ CRED_PART_X509_OCSP_REQ_ASN1_DER,
+ /** a DER encoded X509 OCSP response */
+ CRED_PART_X509_OCSP_RES_ASN1_DER,
+ /** a DER encoded X509 attribute certificate */
+ CRED_PART_X509_AC_ASN1_DER,
+ /** a DER encoded PKCS10 certificate request */
+ CRED_PART_PKCS10_ASN1_DER,
+ /** a PGP encoded certificate */
+ CRED_PART_PGP_CERT,
+
+ CRED_PART_END,
+};
+
+/**
+ * Credential encoding and fingerprinting facility.
+ */
+struct cred_encoding_t {
+
+ /**
+ * Encode a credential in a format using several parts, optional caching.
+ *
+ * The variable argument list takes cred_encoding_part_t, followed by part
+ * specific arguments, terminated by CRED_PART_END.
+ * If a cache key is given, the returned encoding points to internal data:
+ * do not free or modify. If no cache key is given, the encoding is
+ * allocated and must be freed by the caller.
+ *
+ * @param type format the credential should be encoded to
+ * @param cache key to use for caching, NULL to not cache
+ * @param encoding encoding result, allocated if caching disabled
+ * @param ... list of (cred_encoding_part_t, data)
+ * @return TRUE if encoding successful
+ */
+ bool (*encode)(cred_encoding_t *this, cred_encoding_type_t type, void *cache,
+ chunk_t *encoding, ...);
+
+ /**
+ * Clear all cached encodings of a given cache key.
+ *
+ * @param cache key used in encode() for caching
+ */
+ void (*clear_cache)(cred_encoding_t *this, void *cache);
+
+ /**
+ * Check for a cached encoding.
+ *
+ * @param type format of the credential encoding
+ * @param cache key to use for caching, as given to encode()
+ * @param encoding encoding result, internal data
+ * @return TRUE if cache entry found
+ */
+ bool (*get_cache)(cred_encoding_t *this, cred_encoding_type_t type,
+ void *cache, chunk_t *encoding);
+
+ /**
+ * Cache a credential encoding created externally.
+ *
+ * After calling cache(), the passed encoding is owned by the cred encoding
+ * facility.
+ *
+ * @param type format of the credential encoding
+ * @param cache key to use for caching, as given to encode()
+ * @param encoding encoding to cache, gets owned by this
+ */
+ void (*cache)(cred_encoding_t *this, cred_encoding_type_t type, void *cache,
+ chunk_t encoding);
+
+ /**
+ * Register a credential encoder function.
+ *
+ * @param encoder credential encoder function to add
+ */
+ void (*add_encoder)(cred_encoding_t *this, cred_encoder_t encoder);
+
+ /**
+ * Unregister a previously registered credential encoder function.
+ *
+ * @param encoder credential encoder function to remove
+ */
+ void (*remove_encoder)(cred_encoding_t *this, cred_encoder_t encoder);
+
+ /**
+ * Destroy a cred_encoding_t.
+ */
+ void (*destroy)(cred_encoding_t *this);
+};
+
+/**
+ * Create a cred_encoding instance.
+ */
+cred_encoding_t *cred_encoding_create();
+
+#endif /** CRED_ENCODING_H_ @}*/
diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c
new file mode 100644
index 000000000..46c36c941
--- /dev/null
+++ b/src/libstrongswan/credentials/credential_manager.c
@@ -0,0 +1,1097 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+#include "credential_manager.h"
+
+#include <library.h>
+#include <debug.h>
+#include <threading/thread_value.h>
+#include <threading/mutex.h>
+#include <threading/rwlock.h>
+#include <utils/linked_list.h>
+#include <credentials/sets/cert_cache.h>
+#include <credentials/sets/auth_cfg_wrapper.h>
+#include <credentials/certificates/x509.h>
+
+/**
+ * Maximum length of a certificate trust chain
+ */
+#define MAX_TRUST_PATH_LEN 7
+
+typedef struct private_credential_manager_t private_credential_manager_t;
+
+/**
+ * private data of credential_manager
+ */
+struct private_credential_manager_t {
+
+ /**
+ * public functions
+ */
+ credential_manager_t public;
+
+ /**
+ * list of credential sets
+ */
+ linked_list_t *sets;
+
+ /**
+ * thread local set of credentials, linked_list_t with credential_set_t's
+ */
+ thread_value_t *local_sets;
+
+ /**
+ * trust relationship and certificate cache
+ */
+ cert_cache_t *cache;
+
+ /**
+ * certificates queued for persistent caching
+ */
+ linked_list_t *cache_queue;
+
+ /**
+ * list of certificate validators, cert_validator_t
+ */
+ linked_list_t *validators;
+
+ /**
+ * read-write lock to sets list
+ */
+ rwlock_t *lock;
+
+ /**
+ * mutex for cache queue
+ */
+ mutex_t *queue_mutex;
+};
+
+/** data to pass to create_private_enumerator */
+typedef struct {
+ private_credential_manager_t *this;
+ key_type_t type;
+ identification_t* keyid;
+} private_data_t;
+
+/** data to pass to create_cert_enumerator */
+typedef struct {
+ private_credential_manager_t *this;
+ certificate_type_t cert;
+ key_type_t key;
+ identification_t *id;
+ bool trusted;
+} cert_data_t;
+
+/** data to pass to create_cdp_enumerator */
+typedef struct {
+ private_credential_manager_t *this;
+ certificate_type_t type;
+ identification_t *id;
+} cdp_data_t;
+
+/** data to pass to create_shared_enumerator */
+typedef struct {
+ private_credential_manager_t *this;
+ shared_key_type_t type;
+ identification_t *me;
+ identification_t *other;
+} shared_data_t;
+
+/** enumerator over local and global sets */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** enumerator over global sets */
+ enumerator_t *global;
+ /** enumerator over local sets */
+ enumerator_t *local;
+} sets_enumerator_t;
+
+
+METHOD(enumerator_t, sets_enumerate, bool,
+ sets_enumerator_t *this, credential_set_t **set)
+{
+ if (this->global)
+ {
+ if (this->global->enumerate(this->global, set))
+ {
+ return TRUE;
+ }
+ /* end of global sets, look for local */
+ this->global->destroy(this->global);
+ this->global = NULL;
+ }
+ if (this->local)
+ {
+ return this->local->enumerate(this->local, set);
+ }
+ return FALSE;
+}
+
+METHOD(enumerator_t, sets_destroy, void,
+ sets_enumerator_t *this)
+{
+ DESTROY_IF(this->global);
+ DESTROY_IF(this->local);
+ free(this);
+}
+
+/**
+ * create an enumerator over both, global and local sets
+ */
+static enumerator_t *create_sets_enumerator(private_credential_manager_t *this)
+{
+ sets_enumerator_t *enumerator;
+ linked_list_t *local;
+
+ INIT(enumerator,
+ .public.enumerate = (void*)_sets_enumerate,
+ .public.destroy = _sets_destroy,
+ .global = this->sets->create_enumerator(this->sets),
+ );
+ local = this->local_sets->get(this->local_sets);
+ if (local)
+ {
+ enumerator->local = local->create_enumerator(local);
+ }
+ return &enumerator->public;
+}
+
+/**
+ * cleanup function for cert data
+ */
+static void destroy_cert_data(cert_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * enumerator constructor for certificates
+ */
+static enumerator_t *create_cert(credential_set_t *set, cert_data_t *data)
+{
+ return set->create_cert_enumerator(set, data->cert, data->key,
+ data->id, data->trusted);
+}
+
+METHOD(credential_manager_t, create_cert_enumerator, enumerator_t*,
+ private_credential_manager_t *this, certificate_type_t certificate,
+ key_type_t key, identification_t *id, bool trusted)
+{
+ cert_data_t *data = malloc_thing(cert_data_t);
+ data->this = this;
+ data->cert = certificate;
+ data->key = key;
+ data->id = id;
+ data->trusted = trusted;
+
+ this->lock->read_lock(this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
+ (void*)create_cert, data,
+ (void*)destroy_cert_data);
+}
+
+METHOD(credential_manager_t, get_cert, certificate_t*,
+ private_credential_manager_t *this, certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ certificate_t *current, *found = NULL;
+ enumerator_t *enumerator;
+
+ enumerator = create_cert_enumerator(this, cert, key, id, trusted);
+ if (enumerator->enumerate(enumerator, &current))
+ {
+ /* TODO: best match? order by keyid, subject, sualtname */
+ found = current->get_ref(current);
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+
+/**
+ * cleanup function for cdp data
+ */
+static void destroy_cdp_data(cdp_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * enumerator constructor for CDPs
+ */
+static enumerator_t *create_cdp(credential_set_t *set, cdp_data_t *data)
+{
+ return set->create_cdp_enumerator(set, data->type, data->id);
+}
+
+METHOD(credential_manager_t, create_cdp_enumerator, enumerator_t*,
+ private_credential_manager_t *this, certificate_type_t type,
+ identification_t *id)
+{
+ cdp_data_t *data;
+
+ INIT(data,
+ .this = this,
+ .type = type,
+ .id = id,
+ );
+ this->lock->read_lock(this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
+ (void*)create_cdp, data,
+ (void*)destroy_cdp_data);
+}
+
+/**
+ * cleanup function for private data
+ */
+static void destroy_private_data(private_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * enumerator constructor for private keys
+ */
+static enumerator_t *create_private(credential_set_t *set, private_data_t *data)
+{
+ return set->create_private_enumerator(set, data->type, data->keyid);
+}
+
+/**
+ * Create an enumerator over private keys
+ */
+static enumerator_t *create_private_enumerator(
+ private_credential_manager_t *this, key_type_t key, identification_t *keyid)
+{
+ private_data_t *data;
+
+ INIT(data,
+ .this = this,
+ .type = key,
+ .keyid = keyid,
+ );
+ this->lock->read_lock(this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
+ (void*)create_private, data,
+ (void*)destroy_private_data);
+}
+
+/**
+ * Look up a private key by its key identifier
+ */
+static private_key_t* get_private_by_keyid(private_credential_manager_t *this,
+ key_type_t key, identification_t *keyid)
+{
+ private_key_t *found = NULL;
+ enumerator_t *enumerator;
+
+ enumerator = create_private_enumerator(this, key, keyid);
+ if (enumerator->enumerate(enumerator, &found))
+ {
+ found->get_ref(found);
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * cleanup function for shared data
+ */
+static void destroy_shared_data(shared_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * enumerator constructor for shared keys
+ */
+static enumerator_t *create_shared(credential_set_t *set, shared_data_t *data)
+{
+ return set->create_shared_enumerator(set, data->type, data->me, data->other);
+}
+
+METHOD(credential_manager_t, create_shared_enumerator, enumerator_t*,
+ private_credential_manager_t *this, shared_key_type_t type,
+ identification_t *me, identification_t *other)
+{
+ shared_data_t *data;
+
+ INIT(data,
+ .this = this,
+ .type = type,
+ .me = me,
+ .other = other,
+ );
+ this->lock->read_lock(this->lock);
+ return enumerator_create_nested(create_sets_enumerator(this),
+ (void*)create_shared, data,
+ (void*)destroy_shared_data);
+}
+
+METHOD(credential_manager_t, get_shared, shared_key_t*,
+ private_credential_manager_t *this, shared_key_type_t type,
+ identification_t *me, identification_t *other)
+{
+ shared_key_t *current, *found = NULL;
+ id_match_t *best_me = ID_MATCH_NONE, *best_other = ID_MATCH_NONE;
+ id_match_t *match_me, *match_other;
+ enumerator_t *enumerator;
+
+ enumerator = create_shared_enumerator(this, type, me, other);
+ while (enumerator->enumerate(enumerator, &current, &match_me, &match_other))
+ {
+ if (match_other > best_other ||
+ (match_other == best_other && match_me > best_me))
+ {
+ DESTROY_IF(found);
+ found = current->get_ref(current);
+ best_me = match_me;
+ best_other = match_other;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+METHOD(credential_manager_t, add_local_set, void,
+ private_credential_manager_t *this, credential_set_t *set)
+{
+ linked_list_t *sets;
+
+ sets = this->local_sets->get(this->local_sets);
+ if (!sets)
+ { /* first invocation */
+ sets = linked_list_create();
+ this->local_sets->set(this->local_sets, sets);
+ }
+ sets->insert_last(sets, set);
+}
+
+METHOD(credential_manager_t, remove_local_set, void,
+ private_credential_manager_t *this, credential_set_t *set)
+{
+ linked_list_t *sets;
+
+ sets = this->local_sets->get(this->local_sets);
+ sets->remove(sets, set, NULL);
+}
+
+METHOD(credential_manager_t, cache_cert, void,
+ private_credential_manager_t *this, certificate_t *cert)
+{
+ credential_set_t *set;
+ enumerator_t *enumerator;
+
+ if (this->lock->try_write_lock(this->lock))
+ {
+ enumerator = this->sets->create_enumerator(this->sets);
+ while (enumerator->enumerate(enumerator, &set))
+ {
+ set->cache_cert(set, cert);
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ }
+ else
+ { /* we can't cache now as other threads are active, queue for later */
+ this->queue_mutex->lock(this->queue_mutex);
+ this->cache_queue->insert_last(this->cache_queue, cert->get_ref(cert));
+ this->queue_mutex->unlock(this->queue_mutex);
+ }
+}
+
+/**
+ * Try to cache certificates queued for caching
+ */
+static void cache_queue(private_credential_manager_t *this)
+{
+ credential_set_t *set;
+ certificate_t *cert;
+ enumerator_t *enumerator;
+
+ this->queue_mutex->lock(this->queue_mutex);
+ if (this->cache_queue->get_count(this->cache_queue) > 0 &&
+ this->lock->try_write_lock(this->lock))
+ {
+ while (this->cache_queue->remove_last(this->cache_queue,
+ (void**)&cert) == SUCCESS)
+ {
+ enumerator = this->sets->create_enumerator(this->sets);
+ while (enumerator->enumerate(enumerator, &set))
+ {
+ set->cache_cert(set, cert);
+ }
+ enumerator->destroy(enumerator);
+ cert->destroy(cert);
+ }
+ this->lock->unlock(this->lock);
+ }
+ this->queue_mutex->unlock(this->queue_mutex);
+}
+
+/**
+ * check a certificate for its lifetime
+ */
+static bool check_certificate(private_credential_manager_t *this,
+ certificate_t *subject, certificate_t *issuer,
+ bool online, int pathlen, auth_cfg_t *auth)
+{
+ time_t not_before, not_after;
+ cert_validator_t *validator;
+ enumerator_t *enumerator;
+
+ if (!subject->get_validity(subject, NULL, &not_before, &not_after))
+ {
+ DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
+ &not_before, FALSE, &not_after, FALSE);
+ return FALSE;
+ }
+ if (!issuer->get_validity(issuer, NULL, &not_before, &not_after))
+ {
+ DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
+ &not_before, FALSE, &not_after, FALSE);
+ return FALSE;
+ }
+ if (issuer->get_type(issuer) == CERT_X509 &&
+ subject->get_type(subject) == CERT_X509)
+ {
+ int pathlen_constraint;
+ x509_t *x509;
+
+ /* check path length constraint */
+ x509 = (x509_t*)issuer;
+ pathlen_constraint = x509->get_pathLenConstraint(x509);
+ if (pathlen_constraint != X509_NO_PATH_LEN_CONSTRAINT &&
+ pathlen > pathlen_constraint)
+ {
+ DBG1(DBG_CFG, "path length of %d violates constraint of %d",
+ pathlen, pathlen_constraint);
+ return FALSE;
+ }
+ }
+
+ enumerator = this->validators->create_enumerator(this->validators);
+ while (enumerator->enumerate(enumerator, &validator))
+ {
+ if (!validator->validate(validator, subject, issuer,
+ online, pathlen, auth))
+ {
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return TRUE;
+}
+
+/**
+ * Get a trusted certificate from a credential set
+ */
+static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
+ key_type_t type, identification_t *id)
+{
+ certificate_t *subject;
+ public_key_t *public;
+
+ subject = get_cert(this, CERT_ANY, type, id, TRUE);
+ if (!subject)
+ {
+ return NULL;
+ }
+ public = subject->get_public_key(subject);
+ if (!public)
+ {
+ subject->destroy(subject);
+ return NULL;
+ }
+ public->destroy(public);
+ return subject;
+}
+
+/**
+ * Get the issuing certificate of a subject certificate
+ */
+static certificate_t *get_issuer_cert(private_credential_manager_t *this,
+ certificate_t *subject, bool trusted)
+{
+ enumerator_t *enumerator;
+ certificate_t *issuer = NULL, *candidate;
+
+ enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY,
+ subject->get_issuer(subject), trusted);
+ while (enumerator->enumerate(enumerator, &candidate))
+ {
+ if (this->cache->issued_by(this->cache, subject, candidate))
+ {
+ issuer = candidate->get_ref(candidate);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return issuer;
+}
+
+/**
+ * try to verify the trust chain of subject, return TRUE if trusted
+ */
+static bool verify_trust_chain(private_credential_manager_t *this,
+ certificate_t *subject, auth_cfg_t *result,
+ bool trusted, bool online)
+{
+ certificate_t *current, *issuer;
+ auth_cfg_t *auth;
+ int pathlen;
+
+ auth = auth_cfg_create();
+ current = subject->get_ref(subject);
+
+ for (pathlen = 0; pathlen <= MAX_TRUST_PATH_LEN; pathlen++)
+ {
+ issuer = get_issuer_cert(this, current, TRUE);
+ if (issuer)
+ {
+ /* accept only self-signed CAs as trust anchor */
+ if (this->cache->issued_by(this->cache, issuer, issuer))
+ {
+ auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
+ DBG1(DBG_CFG, " using trusted ca certificate \"%Y\"",
+ issuer->get_subject(issuer));
+ trusted = TRUE;
+ }
+ else
+ {
+ auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
+ DBG1(DBG_CFG, " using trusted intermediate ca certificate "
+ "\"%Y\"", issuer->get_subject(issuer));
+ }
+ }
+ else
+ {
+ issuer = get_issuer_cert(this, current, FALSE);
+ if (issuer)
+ {
+ if (current->equals(current, issuer))
+ {
+ DBG1(DBG_CFG, " self-signed certificate \"%Y\" is not trusted",
+ current->get_subject(current));
+ issuer->destroy(issuer);
+ break;
+ }
+ auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
+ DBG1(DBG_CFG, " using untrusted intermediate certificate "
+ "\"%Y\"", issuer->get_subject(issuer));
+ }
+ else
+ {
+ DBG1(DBG_CFG, "no issuer certificate found for \"%Y\"",
+ current->get_subject(current));
+ break;
+ }
+ }
+ if (!check_certificate(this, current, issuer, online, pathlen,
+ current == subject ? auth : NULL))
+ {
+ trusted = FALSE;
+ issuer->destroy(issuer);
+ break;
+ }
+ current->destroy(current);
+ current = issuer;
+ if (trusted)
+ {
+ DBG1(DBG_CFG, " reached self-signed root ca with a path length of %d",
+ pathlen);
+ break;
+ }
+ }
+ current->destroy(current);
+ if (pathlen > MAX_TRUST_PATH_LEN)
+ {
+ DBG1(DBG_CFG, "maximum path length of %d exceeded", MAX_TRUST_PATH_LEN);
+ }
+ if (trusted)
+ {
+ result->merge(result, auth, FALSE);
+ }
+ auth->destroy(auth);
+ return trusted;
+}
+
+/**
+ * enumerator for trusted certificates
+ */
+typedef struct {
+ /** implements enumerator_t interface */
+ enumerator_t public;
+ /** enumerator over candidate peer certificates */
+ enumerator_t *candidates;
+ /** reference to the credential_manager */
+ private_credential_manager_t *this;
+ /** type of the requested key */
+ key_type_t type;
+ /** identity the requested key belongs to */
+ identification_t *id;
+ /** TRUE to do CRL/OCSP checking */
+ bool online;
+ /** pretrusted certificate we have served at first invocation */
+ certificate_t *pretrusted;
+ /** currently enumerating auth config */
+ auth_cfg_t *auth;
+} trusted_enumerator_t;
+
+METHOD(enumerator_t, trusted_enumerate, bool,
+ trusted_enumerator_t *this, certificate_t **cert, auth_cfg_t **auth)
+{
+ certificate_t *current;
+
+ DESTROY_IF(this->auth);
+ this->auth = auth_cfg_create();
+
+ if (!this->candidates)
+ {
+ /* first invocation, build enumerator for next one */
+ this->candidates = create_cert_enumerator(this->this, CERT_ANY,
+ this->type, this->id, FALSE);
+ /* check if we have a trusted certificate for that peer */
+ this->pretrusted = get_pretrusted_cert(this->this, this->type, this->id);
+ if (this->pretrusted)
+ {
+ /* if we find a trusted self signed certificate, we just accept it.
+ * However, in order to fulfill authorization rules, we try to build
+ * the trust chain if it is not self signed */
+ if (this->this->cache->issued_by(this->this->cache,
+ this->pretrusted, this->pretrusted) ||
+ verify_trust_chain(this->this, this->pretrusted, this->auth,
+ TRUE, this->online))
+ {
+ this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
+ this->pretrusted->get_ref(this->pretrusted));
+ DBG1(DBG_CFG, " using trusted certificate \"%Y\"",
+ this->pretrusted->get_subject(this->pretrusted));
+ *cert = this->pretrusted;
+ if (auth)
+ {
+ *auth = this->auth;
+ }
+ return TRUE;
+ }
+ }
+ }
+ /* try to verify the trust chain for each certificate found */
+ while (this->candidates->enumerate(this->candidates, &current))
+ {
+ if (this->pretrusted &&
+ this->pretrusted->equals(this->pretrusted, current))
+ { /* skip pretrusted certificate we already served */
+ continue;
+ }
+
+ DBG1(DBG_CFG, " using certificate \"%Y\"",
+ current->get_subject(current));
+ if (verify_trust_chain(this->this, current, this->auth, FALSE,
+ this->online))
+ {
+ *cert = current;
+ if (auth)
+ {
+ *auth = this->auth;
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(enumerator_t, trusted_destroy, void,
+ trusted_enumerator_t *this)
+{
+ DESTROY_IF(this->pretrusted);
+ DESTROY_IF(this->auth);
+ DESTROY_IF(this->candidates);
+ free(this);
+}
+
+METHOD(credential_manager_t, create_trusted_enumerator, enumerator_t*,
+ private_credential_manager_t *this, key_type_t type,
+ identification_t *id, bool online)
+{
+ trusted_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_trusted_enumerate,
+ .destroy = _trusted_destroy,
+ },
+ .this = this,
+ .type = type,
+ .id = id,
+ .online = online,
+ );
+ return &enumerator->public;
+}
+
+/**
+ * enumerator for public keys
+ */
+typedef struct {
+ /** implements enumerator_t interface */
+ enumerator_t public;
+ /** enumerator over candidate peer certificates */
+ enumerator_t *inner;
+ /** reference to the credential_manager */
+ private_credential_manager_t *this;
+ /** currently enumerating key */
+ public_key_t *current;
+ /** credset wrapper around auth config */
+ auth_cfg_wrapper_t *wrapper;
+} public_enumerator_t;
+
+METHOD(enumerator_t, public_enumerate, bool,
+ public_enumerator_t *this, public_key_t **key, auth_cfg_t **auth)
+{
+ certificate_t *cert;
+
+ while (this->inner->enumerate(this->inner, &cert, auth))
+ {
+ DESTROY_IF(this->current);
+ this->current = cert->get_public_key(cert);
+ if (this->current)
+ {
+ *key = this->current;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+METHOD(enumerator_t, public_destroy, void,
+ public_enumerator_t *this)
+{
+ DESTROY_IF(this->current);
+ this->inner->destroy(this->inner);
+ if (this->wrapper)
+ {
+ remove_local_set(this->this, &this->wrapper->set);
+ this->wrapper->destroy(this->wrapper);
+ }
+ this->this->lock->unlock(this->this->lock);
+
+ /* check for delayed certificate cache queue */
+ cache_queue(this->this);
+ free(this);
+}
+
+METHOD(credential_manager_t, create_public_enumerator, enumerator_t*,
+ private_credential_manager_t *this, key_type_t type, identification_t *id,
+ auth_cfg_t *auth)
+{
+ public_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_public_enumerate,
+ .destroy = _public_destroy,
+ },
+ .inner = create_trusted_enumerator(this, type, id, TRUE),
+ .this = this,
+ );
+ if (auth)
+ {
+ enumerator->wrapper = auth_cfg_wrapper_create(auth);
+ add_local_set(this, &enumerator->wrapper->set);
+ }
+ this->lock->read_lock(this->lock);
+ return &enumerator->public;
+}
+
+/**
+ * Check if a certificate's keyid is contained in the auth helper
+ */
+static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert)
+{
+ enumerator_t *enumerator;
+ identification_t *value;
+ auth_rule_t type;
+ bool found = FALSE;
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &type, &value))
+ {
+ if (type == AUTH_RULE_CA_CERT &&
+ cert->equals(cert, (certificate_t*)value))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
+ * build a trustchain from subject up to a trust anchor in trusted
+ */
+static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
+ certificate_t *subject, auth_cfg_t *auth)
+{
+ certificate_t *issuer, *current;
+ auth_cfg_t *trustchain;
+ int pathlen = 0;
+
+ trustchain = auth_cfg_create();
+
+ current = auth->get(auth, AUTH_RULE_CA_CERT);
+ if (!current)
+ {
+ /* no trust anchor specified, return this cert only */
+ trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT,
+ subject->get_ref(subject));
+ return trustchain;
+ }
+ current = subject->get_ref(subject);
+ while (TRUE)
+ {
+ if (auth_contains_cacert(auth, current))
+ {
+ trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
+ return trustchain;
+ }
+ if (subject == current)
+ {
+ trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current);
+ }
+ else
+ {
+ trustchain->add(trustchain, AUTH_RULE_IM_CERT, current);
+ }
+ issuer = get_issuer_cert(this, current, FALSE);
+ if (!issuer || issuer->equals(issuer, current) ||
+ pathlen > MAX_TRUST_PATH_LEN)
+ {
+ DESTROY_IF(issuer);
+ break;
+ }
+ current = issuer;
+ pathlen++;
+ }
+ trustchain->destroy(trustchain);
+ return NULL;
+}
+
+/**
+ * find a private key of a give certificate
+ */
+static private_key_t *get_private_by_cert(private_credential_manager_t *this,
+ certificate_t *cert, key_type_t type)
+{
+ private_key_t *private = NULL;
+ identification_t *keyid;
+ chunk_t chunk;
+ public_key_t *public;
+
+ public = cert->get_public_key(cert);
+ if (public)
+ {
+ if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
+ {
+ keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
+ private = get_private_by_keyid(this, type, keyid);
+ keyid->destroy(keyid);
+ }
+ public->destroy(public);
+ }
+ return private;
+}
+
+METHOD(credential_manager_t, get_private, private_key_t*,
+ private_credential_manager_t *this, key_type_t type, identification_t *id,
+ auth_cfg_t *auth)
+{
+ enumerator_t *enumerator;
+ certificate_t *cert;
+ private_key_t *private = NULL;
+ auth_cfg_t *trustchain;
+
+ /* check if this is a lookup by key ID, and do it if so */
+ if (id && id->get_type(id) == ID_KEY_ID)
+ {
+ private = get_private_by_keyid(this, type, id);
+ if (private)
+ {
+ return private;
+ }
+ }
+
+ /* if a specific certificate is preferred, check for a matching key */
+ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
+ if (cert)
+ {
+ private = get_private_by_cert(this, cert, type);
+ if (private)
+ {
+ trustchain = build_trustchain(this, cert, auth);
+ if (trustchain)
+ {
+ auth->merge(auth, trustchain, FALSE);
+ trustchain->destroy(trustchain);
+ }
+ return private;
+ }
+ }
+
+ /* try to build a trust chain for each certificate found */
+ enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ private = get_private_by_cert(this, cert, type);
+ if (private)
+ {
+ trustchain = build_trustchain(this, cert, auth);
+ if (trustchain)
+ {
+ auth->merge(auth, trustchain, FALSE);
+ trustchain->destroy(trustchain);
+ break;
+ }
+ private->destroy(private);
+ private = NULL;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* if no valid trustchain was found, fall back to the first usable cert */
+ if (!private)
+ {
+ enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ private = get_private_by_cert(this, cert, type);
+ if (private)
+ {
+ auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ return private;
+}
+
+METHOD(credential_manager_t, flush_cache, void,
+ private_credential_manager_t *this, certificate_type_t type)
+{
+ this->cache->flush(this->cache, type);
+}
+
+METHOD(credential_manager_t, issued_by, bool,
+ private_credential_manager_t *this, certificate_t *subject,
+ certificate_t *issuer)
+{
+ return this->cache->issued_by(this->cache, subject, issuer);
+}
+
+METHOD(credential_manager_t, add_set, void,
+ private_credential_manager_t *this, credential_set_t *set)
+{
+ this->lock->write_lock(this->lock);
+ this->sets->insert_last(this->sets, set);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(credential_manager_t, remove_set, void,
+ private_credential_manager_t *this, credential_set_t *set)
+{
+ this->lock->write_lock(this->lock);
+ this->sets->remove(this->sets, set, NULL);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(credential_manager_t, add_validator, void,
+ private_credential_manager_t *this, cert_validator_t *vdtr)
+{
+ this->lock->write_lock(this->lock);
+ this->sets->insert_last(this->validators, vdtr);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(credential_manager_t, remove_validator, void,
+ private_credential_manager_t *this, cert_validator_t *vdtr)
+{
+ this->lock->write_lock(this->lock);
+ this->validators->remove(this->validators, vdtr, NULL);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(credential_manager_t, destroy, void,
+ private_credential_manager_t *this)
+{
+ cache_queue(this);
+ this->cache_queue->destroy(this->cache_queue);
+ this->sets->remove(this->sets, this->cache, NULL);
+ this->sets->destroy(this->sets);
+ this->local_sets->destroy(this->local_sets);
+ this->cache->destroy(this->cache);
+ this->validators->destroy(this->validators);
+ this->lock->destroy(this->lock);
+ this->queue_mutex->destroy(this->queue_mutex);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+credential_manager_t *credential_manager_create()
+{
+ private_credential_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .create_cert_enumerator = _create_cert_enumerator,
+ .create_shared_enumerator = _create_shared_enumerator,
+ .create_cdp_enumerator = _create_cdp_enumerator,
+ .get_cert = _get_cert,
+ .get_shared = _get_shared,
+ .get_private = _get_private,
+ .create_trusted_enumerator = _create_trusted_enumerator,
+ .create_public_enumerator = _create_public_enumerator,
+ .flush_cache = _flush_cache,
+ .cache_cert = _cache_cert,
+ .issued_by = _issued_by,
+ .add_set = _add_set,
+ .remove_set = _remove_set,
+ .add_local_set = _add_local_set,
+ .remove_local_set = _remove_local_set,
+ .add_validator = _add_validator,
+ .remove_validator = _remove_validator,
+ .destroy = _destroy,
+ },
+ .sets = linked_list_create(),
+ .validators = linked_list_create(),
+ .cache = cert_cache_create(),
+ .cache_queue = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .queue_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ );
+
+ this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
+ this->sets->insert_first(this->sets, this->cache);
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/credentials/credential_manager.h b/src/libstrongswan/credentials/credential_manager.h
new file mode 100644
index 000000000..04269cfbf
--- /dev/null
+++ b/src/libstrongswan/credentials/credential_manager.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2007-2009 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 credential_manager credential_manager
+ * @{ @ingroup credentials
+ */
+
+#ifndef CREDENTIAL_MANAGER_H_
+#define CREDENTIAL_MANAGER_H_
+
+typedef struct credential_manager_t credential_manager_t;
+
+#include <utils/identification.h>
+#include <utils/enumerator.h>
+#include <credentials/auth_cfg.h>
+#include <credentials/credential_set.h>
+#include <credentials/keys/private_key.h>
+#include <credentials/keys/shared_key.h>
+#include <credentials/certificates/certificate.h>
+#include <credentials/cert_validator.h>
+
+/**
+ * Manages credentials using credential_sets.
+ *
+ * The credential manager is the entry point of the credential framework. It
+ * uses so called "sets" to access credentials in a modular fashion, these
+ * are implemented through the credential_set_t interface.
+ * The manager additionally does trust chain verification and trust status
+ * chaching. A set may call the managers methods if it needs credentials itself,
+ * the manager uses recursive locking.
+ *
+ * @verbatim
+
+ +-------+ +----------------+
+ | A | | | +------------------+
+ | u | -----> | | ------> | +------------------+
+ | t | | credential- | | | +------------------+
+ | h | -----> | manager | ------> +--| | credential- | => IPC
+ | e | | | +--| sets |
+ | n | +--> | | ------> +------------------+
+ | t | | | | |
+ | i | | | | |
+ | c | | +----------------+ |
+ | a | | |
+ | t | +----------------------------------------------+
+ | o | may be recursive
+ | r |
+ +-------+
+
+ @endverbatim
+ *
+ * The credential manager uses rwlocks for performance reasons, credential
+ * sets must be fully thread save.
+ */
+struct credential_manager_t {
+
+ /**
+ * Create an enumerator over all certificates.
+ *
+ * @param cert kind of certificate
+ * @param key kind of key in certificate
+ * @param id subject this certificate belongs to
+ * @param trusted TRUE to list trusted certificates only
+ * @return enumerator over the certificates
+ */
+ enumerator_t *(*create_cert_enumerator)(credential_manager_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted);
+ /**
+ * Create an enumerator over all shared keys.
+ *
+ * The enumerator enumerates over:
+ * shared_key_t*, id_match_t me, id_match_t other
+ * But must accepts values for the id_matches.
+ *
+ * @param type kind of requested shared key
+ * @param first first subject between key is shared
+ * @param second second subject between key is shared
+ * @return enumerator over shared keys
+ */
+ enumerator_t *(*create_shared_enumerator)(credential_manager_t *this,
+ shared_key_type_t type,
+ identification_t *first, identification_t *second);
+ /**
+ * Create an enumerator over all Certificate Distribution Points.
+ *
+ * @param type kind of certificate the point distributes
+ * @param id identification of the distributed certificate
+ * @return enumerator of CDPs as char*
+ */
+ enumerator_t *(*create_cdp_enumerator)(credential_manager_t *this,
+ certificate_type_t type, identification_t *id);
+ /**
+ * Get a trusted or untrusted certificate.
+ *
+ * @param cert kind of certificate
+ * @param key kind of key in certificate
+ * @param id subject this certificate belongs to
+ * @param trusted TRUE to get a trusted certificate only
+ * @return certificate, if found, NULL otherwise
+ */
+ certificate_t *(*get_cert)(credential_manager_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted);
+ /**
+ * Get the best matching shared key for two IDs.
+ *
+ * @param type kind of requested shared key
+ * @param me own identity
+ * @param other peers identity
+ * @return shared_key_t, NULL if none found
+ */
+ shared_key_t *(*get_shared)(credential_manager_t *this, shared_key_type_t type,
+ identification_t *me, identification_t *other);
+ /**
+ * Get a private key to create a signature.
+ *
+ * The get_private() method gets a secret private key identified by either
+ * the keyid itself or an id the key belongs to.
+ * The auth parameter contains additional information, such as receipients
+ * trusted CA certs. Auth gets filled with subject and CA certificates
+ * needed to validate a created signature.
+ *
+ * @param type type of the key to get
+ * @param id identification the key belongs to
+ * @param auth auth config, including trusted CA certificates
+ * @return private_key_t, NULL if none found
+ */
+ private_key_t* (*get_private)(credential_manager_t *this, key_type_t type,
+ identification_t *id, auth_cfg_t *auth);
+
+ /**
+ * Create an enumerator over trusted certificates.
+ *
+ * This method creates an enumerator over trusted certificates. The auth
+ * parameter (if given) recevies the trustchain used to validate
+ * the certificate. The resulting enumerator enumerates over
+ * certificate_t*, auth_cfg_t*.
+ * If online is set, revocations are checked online for the whole
+ * trustchain.
+ *
+ * @param type type of the key we want a certificate for
+ * @param id subject of the certificate
+ * @param online whether revocations should be checked online
+ * @return enumerator
+ */
+ enumerator_t* (*create_trusted_enumerator)(credential_manager_t *this,
+ key_type_t type, identification_t *id, bool online);
+
+ /**
+ * Create an enumerator over trusted public keys.
+ *
+ * This method gets a an enumerator over trusted public keys to verify a
+ * signature created by id. The auth parameter contains additional
+ * authentication infos, e.g. peer and intermediate certificates.
+ * The resulting enumerator enumerates over public_key_t *, auth_cfg_t *,
+ * where the auth config helper contains rules for constraint checks.
+ * This function is very similar to create_trusted_enumerator(), but
+ * gets public keys directly.
+ *
+ * @param type type of the key to get
+ * @param id owner of the key, signer of the signature
+ * @param auth authentication infos
+ * @return enumerator
+ */
+ enumerator_t* (*create_public_enumerator)(credential_manager_t *this,
+ key_type_t type, identification_t *id, auth_cfg_t *auth);
+
+ /**
+ * Cache a certificate by invoking cache_cert() on all registerd sets.
+ *
+ * @param cert certificate to cache
+ */
+ void (*cache_cert)(credential_manager_t *this, certificate_t *cert);
+
+ /**
+ * Flush the certificate cache.
+ *
+ * Only the managers local cache is flushed, but not the sets cache filled
+ * by the cache_cert() method.
+ *
+ * @param type type of certificate to flush, or CERT_ANY
+ */
+ void (*flush_cache)(credential_manager_t *this, certificate_type_t type);
+
+ /**
+ * Check if a given subject certificate is issued by an issuer certificate.
+ *
+ * This operation does signature verification, but uses the credential
+ * managers cache for to speed up the operation.
+ *
+ * @param subject subject certificate to check
+ * @param issuer issuer certificate that potentially has signed subject
+ * @return TRUE if issuer signed subject
+ */
+ bool (*issued_by)(credential_manager_t *this,
+ certificate_t *subject, certificate_t *issuer);
+
+ /**
+ * Register a credential set to the manager.
+ *
+ * @param set set to register
+ */
+ void (*add_set)(credential_manager_t *this, credential_set_t *set);
+
+ /**
+ * Unregister a credential set from the manager.
+ *
+ * @param set set to unregister
+ */
+ void (*remove_set)(credential_manager_t *this, credential_set_t *set);
+
+ /**
+ * Register a thread local credential set to the manager.
+ *
+ * To add a credential set for the current trustchain verification
+ * operation, sets may be added for the calling thread only. This
+ * does not require a write lock and is therefore a much less expensive
+ * operation.
+ *
+ * @param set set to register
+ */
+ void (*add_local_set)(credential_manager_t *this, credential_set_t *set);
+
+ /**
+ * Unregister a thread local credential set from the manager.
+ *
+ * @param set set to unregister
+ */
+ void (*remove_local_set)(credential_manager_t *this, credential_set_t *set);
+
+ /**
+ * Register a certificate validator to the manager.
+ *
+ * @param vdtr validator to register
+ */
+ void (*add_validator)(credential_manager_t *this, cert_validator_t *vdtr);
+
+ /**
+ * Remove a certificate validator from the manager.
+ *
+ * @param vdtr validator to unregister
+ */
+ void (*remove_validator)(credential_manager_t *this, cert_validator_t *vdtr);
+
+ /**
+ * Destroy a credential_manager instance.
+ */
+ void (*destroy)(credential_manager_t *this);
+};
+
+/**
+ * Create a credential_manager instance.
+ */
+credential_manager_t *credential_manager_create();
+
+#endif /** CREDENTIAL_MANAGER_H_ @}*/
diff --git a/src/libstrongswan/credentials/credential_set.h b/src/libstrongswan/credentials/credential_set.h
new file mode 100644
index 000000000..0eee237cb
--- /dev/null
+++ b/src/libstrongswan/credentials/credential_set.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2007 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 credential_set credential_set
+ * @{ @ingroup credentials
+ */
+
+#ifndef CREDENTIAL_SET_H_
+#define CREDENTIAL_SET_H_
+
+typedef struct credential_set_t credential_set_t;
+
+#include <credentials/keys/public_key.h>
+#include <credentials/keys/shared_key.h>
+#include <credentials/certificates/certificate.h>
+
+/**
+ * A set of credentials.
+ *
+ * Contains private keys, shared keys and different kinds of certificates.
+ * Enumerators are used because queries might return multiple matches.
+ * Filter parameters restrict enumeration over specific items only.
+ * See credential_manager_t for an overview of the credential framework.
+ *
+ * A credential set enumerator may not block the credential set, i.e. multiple
+ * threads must be able to hold multiple enumerators, as the credential manager
+ * is higly parallelized. The best way to achieve this is by using shared
+ * read locks for the enumerators only. Otherwiese deadlocks will occur.
+ * The writing cache_cert() routine is called by the manager only if no
+ * enumerator is alive, so it is save to use a write lock there.
+ */
+struct credential_set_t {
+
+ /**
+ * Create an enumerator over private keys (private_key_t).
+ *
+ * The id is either a key identifier of the requested key, or an identity
+ * of the key owner.
+ *
+ * @param type type of requested private key
+ * @param id key identifier/owner
+ * @return enumerator over private_key_t's.
+ */
+ enumerator_t *(*create_private_enumerator)(credential_set_t *this,
+ key_type_t type, identification_t *id);
+ /**
+ * Create an enumerator over certificates (certificate_t).
+ *
+ * @param cert kind of certificate
+ * @param key kind of key in certificate
+ * @param id identity (subject) this certificate belongs to
+ * @param trusted whether the certificate must be trustworthy
+ * @return enumerator as described above
+ */
+ enumerator_t *(*create_cert_enumerator)(credential_set_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted);
+ /**
+ * Create an enumerator over shared keys (shared_key_t).
+ *
+ * The enumerator enumerates over:
+ * shared_key_t*, id_match_t me, id_match_t other
+ * But must accept NULL values for the id_matches.
+ *
+ * @param type kind of requested shared key
+ * @param me own identity
+ * @param other other identity who owns that secret
+ * @return enumerator as described above
+ */
+ enumerator_t *(*create_shared_enumerator)(credential_set_t *this,
+ shared_key_type_t type,
+ identification_t *me, identification_t *other);
+
+ /**
+ * Create an enumerator over certificate distribution points.
+ *
+ * @param type type of the certificate to get a CDP
+ * @param id identification of the distributed certificate
+ * @return an enumerator over CDPs as char*
+ */
+ enumerator_t *(*create_cdp_enumerator)(credential_set_t *this,
+ certificate_type_t type, identification_t *id);
+
+ /**
+ * Cache a certificate in the credential set.
+ *
+ * The caching policy is implementation dependent, the sets may cache the
+ * certificate in-memory, persistent on disk or not at all.
+ *
+ * @param cert certificate to cache
+ */
+ void (*cache_cert)(credential_set_t *this, certificate_t *cert);
+};
+
+#endif /** CREDENTIAL_SET_H_ @}*/
diff --git a/src/libstrongswan/credentials/ietf_attributes/ietf_attributes.c b/src/libstrongswan/credentials/ietf_attributes/ietf_attributes.c
index ff3ddeb6f..de5b85bae 100644
--- a/src/libstrongswan/credentials/ietf_attributes/ietf_attributes.c
+++ b/src/libstrongswan/credentials/ietf_attributes/ietf_attributes.c
@@ -159,7 +159,7 @@ static char* get_string(private_ietf_attributes_t *this)
enumerator = this->list->create_enumerator(this->list);
while (enumerator->enumerate(enumerator, &attr))
{
- int written = 0;
+ int written;
if (first)
{
@@ -168,8 +168,12 @@ static char* get_string(private_ietf_attributes_t *this)
else
{
written = snprintf(pos, len, ", ");
+ if (written < 0 || written >= len)
+ {
+ break;
+ }
pos += written;
- len -= written;
+ len -= written;
}
switch (attr->type)
@@ -194,8 +198,13 @@ static char* get_string(private_ietf_attributes_t *this)
break;
}
default:
+ written = 0;
break;
}
+ if (written < 0 || written >= len)
+ {
+ break;
+ }
pos += written;
len -= written;
}
diff --git a/src/libstrongswan/credentials/keys/key_encoding.h b/src/libstrongswan/credentials/keys/key_encoding.h
deleted file mode 100644
index d8435f4b4..000000000
--- a/src/libstrongswan/credentials/keys/key_encoding.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2009 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 key_encoding key_encoding
- * @{ @ingroup keys
- */
-
-#ifndef KEY_ENCODING_H_
-#define KEY_ENCODING_H_
-
-typedef struct key_encoding_t key_encoding_t;
-typedef enum key_encoding_type_t key_encoding_type_t;
-typedef enum key_encoding_part_t key_encoding_part_t;
-
-#include <library.h>
-
-/**
- * Key encoder function implementing encoding/fingerprinting.
- *
- * The variable argument list takes key_encoding_part_t, followed by part
- * specific arguments, terminated by KEY_PART_END.
- *
- * @param type format to encode the key to
- * @param args list of (key_encoding_part_t, data)
- * @param encoding encoding result, allocated
- * @return TRUE if encoding successful
- */
-typedef bool (*key_encoder_t)(key_encoding_type_t type, chunk_t *encoding,
- va_list args);
-
-/**
- * Helper function for key_encoder_t implementations to parse argument list.
- *
- * Key encoder functions get a variable argument list to parse. To simplify
- * the job, this function reads the arguments and returns chunks for each
- * part.
- * The argument list of this function takes a key_encoding_part_t, followed
- * by a data pointer receiving the value, terminated by KEY_PART_END.
- *
- * @param args argument list passed to key encoder function
- * @param ... list of (key_encoding_part_t, data*)
- * @return TRUE if all parts found, FALSE otherwise
- */
-bool key_encoding_args(va_list args, ...);
-
-/**
- * Encoding type of a fingerprint/private-/public-key.
- *
- * Fingerprints have have the KEY_ID_*, public keys the KEY_PUB_* and
- * private keys the KEY_PRIV_* prefix.
- */
-enum key_encoding_type_t {
- /** SHA1 fingerprint over subjectPublicKeyInfo */
- KEY_ID_PUBKEY_INFO_SHA1 = 0,
- /** SHA1 fingerprint over subjectPublicKey */
- KEY_ID_PUBKEY_SHA1,
- /** PGPv3 fingerprint */
- KEY_ID_PGPV3,
- /** PGPv4 fingerprint */
- KEY_ID_PGPV4,
-
- KEY_ID_MAX,
-
- /** PKCS#1 and similar ASN.1 key encoding */
- KEY_PUB_ASN1_DER,
- KEY_PRIV_ASN1_DER,
- /** subjectPublicKeyInfo encoding */
- KEY_PUB_SPKI_ASN1_DER,
- /** PEM encoded PKCS#1 key */
- KEY_PUB_PEM,
- KEY_PRIV_PEM,
- /** PGP key encoding */
- KEY_PUB_PGP,
- KEY_PRIV_PGP,
-
- KEY_ENCODING_MAX,
-};
-
-/**
- * Parts of a key to encode.
- */
-enum key_encoding_part_t {
- /** modulus of a RSA key, n */
- KEY_PART_RSA_MODULUS,
- /** public exponent of a RSA key, e */
- KEY_PART_RSA_PUB_EXP,
- /** private exponent of a RSA key, d */
- KEY_PART_RSA_PRIV_EXP,
- /** prime1 a RSA key, p */
- KEY_PART_RSA_PRIME1,
- /** prime2 a RSA key, q */
- KEY_PART_RSA_PRIME2,
- /** exponent1 a RSA key, exp1 */
- KEY_PART_RSA_EXP1,
- /** exponent1 a RSA key, exp2 */
- KEY_PART_RSA_EXP2,
- /** coefficient of RSA key, coeff */
- KEY_PART_RSA_COEFF,
- /** a DER encoded RSA public key */
- KEY_PART_RSA_PUB_ASN1_DER,
- /** a DER encoded RSA private key */
- KEY_PART_RSA_PRIV_ASN1_DER,
- /** a DER encoded ECDSA public key */
- KEY_PART_ECDSA_PUB_ASN1_DER,
- /** a DER encoded ECDSA private key */
- KEY_PART_ECDSA_PRIV_ASN1_DER,
-
- KEY_PART_END,
-};
-
-/**
- * Private/Public key encoding and fingerprinting facility.
- */
-struct key_encoding_t {
-
- /**
- * Encode a key into a format using several key parts, optional caching.
- *
- * The variable argument list takes key_encoding_part_t, followed by part
- * specific arguments, terminated by KEY_PART_END.
- * If a cache key is given, the returned encoding points to internal data:
- * do not free or modify. If no cache key is given, the encoding is
- * allocated and must be freed by the caller.
- *
- * @param type format the key should be encoded to
- * @param cache key to use for caching, NULL to not cache
- * @param encoding encoding result, allocated if caching disabled
- * @param ... list of (key_encoding_part_t, data)
- * @return TRUE if encoding successful
- */
- bool (*encode)(key_encoding_t *this, key_encoding_type_t type, void *cache,
- chunk_t *encoding, ...);
-
- /**
- * Clear all cached encodings of a given cache key.
- *
- * @param cache key used in encode() for caching
- */
- void (*clear_cache)(key_encoding_t *this, void *cache);
-
- /**
- * Check for a cached encoding.
- *
- * @param type format of the key encoding
- * @param cache key to use for caching, as given to encode()
- * @param encoding encoding result, internal data
- * @return TRUE if cache entry found
- */
- bool (*get_cache)(key_encoding_t *this, key_encoding_type_t type,
- void *cache, chunk_t *encoding);
-
- /**
- * Cache a key encoding created externally.
- *
- * After calling cache(), the passed encoding is owned by the key encoding
- * facility.
- *
- * @param type format of the key encoding
- * @param cache key to use for caching, as given to encode()
- * @param encoding encoding to cache, gets owned by this
- */
- void (*cache)(key_encoding_t *this, key_encoding_type_t type, void *cache,
- chunk_t encoding);
-
- /**
- * Register a key encoder function.
- *
- * @param encoder key encoder function to add
- */
- void (*add_encoder)(key_encoding_t *this, key_encoder_t encoder);
-
- /**
- * Unregister a previously registered key encoder function.
- *
- * @param encoder key encoder function to remove
- */
- void (*remove_encoder)(key_encoding_t *this, key_encoder_t encoder);
-
- /**
- * Destroy a key_encoding_t.
- */
- void (*destroy)(key_encoding_t *this);
-};
-
-/**
- * Create a key_encoding instance.
- */
-key_encoding_t *key_encoding_create();
-
-#endif /** KEY_ENCODING_H_ @}*/
diff --git a/src/libstrongswan/credentials/keys/private_key.c b/src/libstrongswan/credentials/keys/private_key.c
index c3b5ac55b..8292af495 100644
--- a/src/libstrongswan/credentials/keys/private_key.c
+++ b/src/libstrongswan/credentials/keys/private_key.c
@@ -20,7 +20,7 @@
*/
bool private_key_equals(private_key_t *this, private_key_t *other)
{
- key_encoding_type_t type;
+ cred_encoding_type_t type;
chunk_t a, b;
if (this == other)
@@ -28,7 +28,7 @@ bool private_key_equals(private_key_t *this, private_key_t *other)
return TRUE;
}
- for (type = 0; type < KEY_ENCODING_MAX; type++)
+ for (type = 0; type < CRED_ENCODING_MAX; type++)
{
if (this->get_fingerprint(this, type, &a) &&
other->get_fingerprint(other, type, &b))
@@ -44,10 +44,10 @@ bool private_key_equals(private_key_t *this, private_key_t *other)
*/
bool private_key_belongs_to(private_key_t *private, public_key_t *public)
{
- key_encoding_type_t type;
+ cred_encoding_type_t type;
chunk_t a, b;
- for (type = 0; type < KEY_ENCODING_MAX; type++)
+ for (type = 0; type < CRED_ENCODING_MAX; type++)
{
if (private->get_fingerprint(private, type, &a) &&
public->get_fingerprint(public, type, &b))
@@ -63,10 +63,10 @@ bool private_key_belongs_to(private_key_t *private, public_key_t *public)
*/
bool private_key_has_fingerprint(private_key_t *private, chunk_t fingerprint)
{
- key_encoding_type_t type;
+ cred_encoding_type_t type;
chunk_t current;
- for (type = 0; type < KEY_ID_MAX; type++)
+ for (type = 0; type < KEYID_MAX; type++)
{
if (private->get_fingerprint(private, type, &current) &&
chunk_equals(current, fingerprint))
diff --git a/src/libstrongswan/credentials/keys/private_key.h b/src/libstrongswan/credentials/keys/private_key.h
index d4517f296..27f4ab098 100644
--- a/src/libstrongswan/credentials/keys/private_key.h
+++ b/src/libstrongswan/credentials/keys/private_key.h
@@ -23,6 +23,7 @@
typedef struct private_key_t private_key_t;
+#include <credentials/cred_encoding.h>
#include <credentials/keys/public_key.h>
/**
@@ -89,11 +90,11 @@ struct private_key_t {
/**
* Get the fingerprint of the key.
*
- * @param type type of fingerprint, one of KEY_ID_*
+ * @param type type of fingerprint, one of KEYID_*
* @param fp fingerprint, points to internal data
* @return TRUE if fingerprint type supported
*/
- bool (*get_fingerprint)(private_key_t *this, key_encoding_type_t type,
+ bool (*get_fingerprint)(private_key_t *this, cred_encoding_type_t type,
chunk_t *fp);
/**
@@ -107,11 +108,11 @@ struct private_key_t {
/**
* Get the key in an encoded form as a chunk.
*
- * @param type type of the encoding, one of KEY_PRIV_*
+ * @param type type of the encoding, one of PRIVKEY_*
* @param encoding encoding of the key, allocated
* @return TRUE if encoding supported
*/
- bool (*get_encoding)(private_key_t *this, key_encoding_type_t type,
+ bool (*get_encoding)(private_key_t *this, cred_encoding_type_t type,
chunk_t *encoding);
/**
diff --git a/src/libstrongswan/credentials/keys/public_key.c b/src/libstrongswan/credentials/keys/public_key.c
index ba3036793..ce342de33 100644
--- a/src/libstrongswan/credentials/keys/public_key.c
+++ b/src/libstrongswan/credentials/keys/public_key.c
@@ -47,7 +47,7 @@ ENUM(signature_scheme_names, SIGN_UNKNOWN, SIGN_ECDSA_521,
*/
bool public_key_equals(public_key_t *this, public_key_t *other)
{
- key_encoding_type_t type;
+ cred_encoding_type_t type;
chunk_t a, b;
if (this == other)
@@ -55,7 +55,7 @@ bool public_key_equals(public_key_t *this, public_key_t *other)
return TRUE;
}
- for (type = 0; type < KEY_ENCODING_MAX; type++)
+ for (type = 0; type < CRED_ENCODING_MAX; type++)
{
if (this->get_fingerprint(this, type, &a) &&
other->get_fingerprint(other, type, &b))
@@ -71,10 +71,10 @@ bool public_key_equals(public_key_t *this, public_key_t *other)
*/
bool public_key_has_fingerprint(public_key_t *public, chunk_t fingerprint)
{
- key_encoding_type_t type;
+ cred_encoding_type_t type;
chunk_t current;
- for (type = 0; type < KEY_ID_MAX; type++)
+ for (type = 0; type < KEYID_MAX; type++)
{
if (public->get_fingerprint(public, type, &current) &&
chunk_equals(current, fingerprint))
diff --git a/src/libstrongswan/credentials/keys/public_key.h b/src/libstrongswan/credentials/keys/public_key.h
index a421e7b5b..ff827a189 100644
--- a/src/libstrongswan/credentials/keys/public_key.h
+++ b/src/libstrongswan/credentials/keys/public_key.h
@@ -23,12 +23,11 @@
typedef struct public_key_t public_key_t;
typedef enum key_type_t key_type_t;
-typedef enum key_id_type_t key_id_type_t;
typedef enum signature_scheme_t signature_scheme_t;
#include <library.h>
#include <utils/identification.h>
-#include <credentials/keys/key_encoding.h>
+#include <credentials/cred_encoding.h>
/**
* Type of a key pair, the used crypto system
@@ -147,11 +146,11 @@ struct public_key_t {
/**
* Get the fingerprint of the key.
*
- * @param type type of fingerprint, one of KEY_ID_*
+ * @param type type of fingerprint, one of KEYID_*
* @param fp fingerprint, points to internal data
* @return TRUE if fingerprint type supported
*/
- bool (*get_fingerprint)(public_key_t *this, key_encoding_type_t type,
+ bool (*get_fingerprint)(public_key_t *this, cred_encoding_type_t type,
chunk_t *fp);
/**
@@ -165,11 +164,11 @@ struct public_key_t {
/**
* Get the key in an encoded form as a chunk.
*
- * @param type type of the encoding, one of KEY_PRIV_*
+ * @param type type of the encoding, one of PRIVKEY_*
* @param encoding encoding of the key, allocated
* @return TRUE if encoding supported
*/
- bool (*get_encoding)(public_key_t *this, key_encoding_type_t type,
+ bool (*get_encoding)(public_key_t *this, cred_encoding_type_t type,
chunk_t *encoding);
/**
diff --git a/src/libstrongswan/credentials/sets/auth_cfg_wrapper.c b/src/libstrongswan/credentials/sets/auth_cfg_wrapper.c
new file mode 100644
index 000000000..5e8458616
--- /dev/null
+++ b/src/libstrongswan/credentials/sets/auth_cfg_wrapper.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2008-2009 Martin Willi
+ * Copyright (C) 2008 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <library.h>
+#include <debug.h>
+
+#include "auth_cfg_wrapper.h"
+
+typedef struct private_auth_cfg_wrapper_t private_auth_cfg_wrapper_t;
+
+/**
+ * private data of auth_cfg_wrapper
+ */
+struct private_auth_cfg_wrapper_t {
+
+ /**
+ * public functions
+ */
+ auth_cfg_wrapper_t public;
+
+ /**
+ * wrapped auth info
+ */
+ auth_cfg_t *auth;
+};
+
+/**
+ * enumerator for auth_cfg_wrapper_t.create_cert_enumerator()
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** inner enumerator from auth_cfg */
+ enumerator_t *inner;
+ /** wrapped auth round */
+ auth_cfg_t *auth;
+ /** enumerated cert type */
+ certificate_type_t cert;
+ /** enumerated key type */
+ key_type_t key;
+ /** enumerated id */
+ identification_t *id;
+} wrapper_enumerator_t;
+
+/**
+ * Tries to fetch a certificate that was supplied as "Hash and URL"
+ * (replaces rule type and value in place).
+ */
+static bool fetch_cert(wrapper_enumerator_t *enumerator,
+ auth_rule_t *rule, void **value)
+{
+ char *url = (char*)*value;
+ if (!url)
+ {
+ /* fetching the certificate previously failed */
+ return FALSE;
+ }
+
+ chunk_t data;
+ certificate_t *cert;
+
+ DBG1(DBG_CFG, " fetching certificate from '%s' ...", url);
+ if (lib->fetcher->fetch(lib->fetcher, url, &data, FETCH_END) != SUCCESS)
+ {
+ DBG1(DBG_CFG, " fetching certificate failed");
+ /* we set the item to NULL, so we can skip it */
+ enumerator->auth->replace(enumerator->auth, enumerator->inner,
+ *rule, NULL);
+ return FALSE;
+ }
+
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, data, BUILD_END);
+ free(data.ptr);
+
+ if (!cert)
+ {
+ DBG1(DBG_CFG, " parsing fetched certificate failed");
+ /* we set the item to NULL, so we can skip it */
+ enumerator->auth->replace(enumerator->auth, enumerator->inner,
+ *rule, NULL);
+ return FALSE;
+ }
+
+ DBG1(DBG_CFG, " fetched certificate \"%Y\"", cert->get_subject(cert));
+ lib->credmgr->cache_cert(lib->credmgr, cert);
+
+ if (*rule == AUTH_HELPER_IM_HASH_URL)
+ {
+ *rule = AUTH_HELPER_IM_CERT;
+ }
+ else
+ {
+ *rule = AUTH_HELPER_SUBJECT_CERT;
+ }
+ *value = cert;
+ enumerator->auth->replace(enumerator->auth, enumerator->inner,
+ *rule, cert->get_ref(cert));
+ return TRUE;
+}
+
+/**
+ * enumerate function for wrapper_enumerator_t
+ */
+static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
+{
+ auth_rule_t rule;
+ certificate_t *current;
+ public_key_t *public;
+
+ while (this->inner->enumerate(this->inner, &rule, &current))
+ {
+ if (rule == AUTH_HELPER_IM_HASH_URL ||
+ rule == AUTH_HELPER_SUBJECT_HASH_URL)
+ { /* on-demand fetching of hash and url certificates */
+ if (!fetch_cert(this, &rule, (void**)&current))
+ {
+ continue;
+ }
+ }
+ else if (rule != AUTH_HELPER_SUBJECT_CERT &&
+ rule != AUTH_HELPER_IM_CERT)
+ { /* handle only HELPER certificates */
+ continue;
+ }
+ if (this->cert != CERT_ANY && this->cert != current->get_type(current))
+ { /* CERT type requested, but does not match */
+ continue;
+ }
+ public = current->get_public_key(current);
+ if (this->key != KEY_ANY && !public)
+ { /* key type requested, but no public key */
+ DESTROY_IF(public);
+ continue;
+ }
+ if (this->key != KEY_ANY && public && this->key != public->get_type(public))
+ { /* key type requested, but public key has another type */
+ DESTROY_IF(public);
+ continue;
+ }
+ DESTROY_IF(public);
+ if (this->id && !current->has_subject(current, this->id))
+ { /* subject requested, but does not match */
+ continue;
+ }
+ *cert = current;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * destroy function for wrapper_enumerator_t
+ */
+static void wrapper_enumerator_destroy(wrapper_enumerator_t *this)
+{
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * implementation of auth_cfg_wrapper_t.set.create_cert_enumerator
+ */
+static enumerator_t *create_enumerator(private_auth_cfg_wrapper_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ wrapper_enumerator_t *enumerator;
+
+ if (trusted)
+ {
+ return NULL;
+ }
+ enumerator = malloc_thing(wrapper_enumerator_t);
+ enumerator->auth = this->auth;
+ enumerator->cert = cert;
+ enumerator->key = key;
+ enumerator->id = id;
+ enumerator->inner = this->auth->create_enumerator(this->auth);
+ enumerator->public.enumerate = (void*)enumerate;
+ enumerator->public.destroy = (void*)wrapper_enumerator_destroy;
+ return &enumerator->public;
+}
+
+/**
+ * Implementation of auth_cfg_wrapper_t.destroy
+ */
+static void destroy(private_auth_cfg_wrapper_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth)
+{
+ private_auth_cfg_wrapper_t *this = malloc_thing(private_auth_cfg_wrapper_t);
+
+ this->public.set.create_private_enumerator = (void*)return_null;
+ this->public.set.create_cert_enumerator = (void*)create_enumerator;
+ this->public.set.create_shared_enumerator = (void*)return_null;
+ this->public.set.create_cdp_enumerator = (void*)return_null;
+ this->public.set.cache_cert = (void*)nop;
+ this->public.destroy = (void(*)(auth_cfg_wrapper_t*))destroy;
+
+ this->auth = auth;
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/credentials/sets/auth_cfg_wrapper.h b/src/libstrongswan/credentials/sets/auth_cfg_wrapper.h
new file mode 100644
index 000000000..3a4b197ac
--- /dev/null
+++ b/src/libstrongswan/credentials/sets/auth_cfg_wrapper.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2008-2009 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 auth_cfg_wrapper auth_cfg_wrapper
+ * @{ @ingroup sets
+ */
+
+#ifndef AUTH_CFG_WRAPPER_H_
+#define AUTH_CFG_WRAPPER_H_
+
+#include <credentials/auth_cfg.h>
+#include <credentials/credential_set.h>
+
+typedef struct auth_cfg_wrapper_t auth_cfg_wrapper_t;
+
+/**
+ * A wrapper around auth_cfg_t to handle it as a credential set.
+ */
+struct auth_cfg_wrapper_t {
+
+ /**
+ * implements credential_set_t
+ */
+ credential_set_t set;
+
+ /**
+ * Destroy a auth_cfg_wrapper instance.
+ */
+ void (*destroy)(auth_cfg_wrapper_t *this);
+};
+
+/**
+ * Create a auth_cfg_wrapper instance.
+ *
+ * @param auth the wrapped auth info
+ * @return wrapper around auth
+ */
+auth_cfg_wrapper_t *auth_cfg_wrapper_create(auth_cfg_t *auth);
+
+#endif /** AUTH_CFG_WRAPPER_H_ @}*/
diff --git a/src/libstrongswan/credentials/sets/cert_cache.c b/src/libstrongswan/credentials/sets/cert_cache.c
new file mode 100644
index 000000000..7161ac9ac
--- /dev/null
+++ b/src/libstrongswan/credentials/sets/cert_cache.c
@@ -0,0 +1,389 @@
+/*
+ * 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.
+ */
+
+#include "cert_cache.h"
+
+#include <time.h>
+#include <sched.h>
+
+#include <library.h>
+#include <threading/rwlock.h>
+#include <utils/linked_list.h>
+
+/** cache size, a power of 2 for fast modulo */
+#define CACHE_SIZE 32
+
+/** attempts to acquire a cache lock */
+#define REPLACE_TRIES 5
+
+typedef struct private_cert_cache_t private_cert_cache_t;
+typedef struct relation_t relation_t;
+
+/**
+ * A trusted relation between subject and issuer
+ */
+struct relation_t {
+
+ /**
+ * subject of this relation
+ */
+ certificate_t *subject;
+
+ /**
+ * issuer of this relation
+ */
+ certificate_t *issuer;
+
+ /**
+ * Cache hits
+ */
+ u_int hits;
+
+ /**
+ * Lock for this relation
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * private data of cert_cache
+ */
+struct private_cert_cache_t {
+
+ /**
+ * public functions
+ */
+ cert_cache_t public;
+
+ /**
+ * array of trusted subject-issuer relations
+ */
+ relation_t relations[CACHE_SIZE];
+};
+
+/**
+ * Cache relation in a free slot/replace an other
+ */
+static void cache(private_cert_cache_t *this,
+ certificate_t *subject, certificate_t *issuer)
+{
+ relation_t *rel;
+ int i, offset, try;
+ u_int total_hits = 0;
+
+ /* check for a unused relation slot first */
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ rel = &this->relations[i];
+
+ if (!rel->subject && rel->lock->try_write_lock(rel->lock))
+ {
+ /* double-check having lock */
+ if (!rel->subject)
+ {
+ rel->subject = subject->get_ref(subject);
+ rel->issuer = issuer->get_ref(issuer);
+ return rel->lock->unlock(rel->lock);
+ }
+ rel->lock->unlock(rel->lock);
+ }
+ total_hits += rel->hits;
+ }
+ /* run several attempts to replace a random slot, never block. */
+ for (try = 0; try < REPLACE_TRIES; try++)
+ {
+ /* replace a random relation */
+ offset = random();
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ rel = &this->relations[(i + offset) % CACHE_SIZE];
+
+ if (rel->hits > total_hits / CACHE_SIZE)
+ { /* skip often used slots */
+ continue;
+ }
+ if (rel->lock->try_write_lock(rel->lock))
+ {
+ if (rel->subject)
+ {
+ rel->subject->destroy(rel->subject);
+ rel->issuer->destroy(rel->issuer);
+ }
+ rel->subject = subject->get_ref(subject);
+ rel->issuer = issuer->get_ref(issuer);
+ rel->hits = 0;
+ return rel->lock->unlock(rel->lock);
+ }
+ }
+ /* give other threads a chance to release locks */
+ sched_yield();
+ }
+}
+
+/**
+ * Implementation of cert_cache_t.issued_by.
+ */
+static bool issued_by(private_cert_cache_t *this,
+ certificate_t *subject, certificate_t *issuer)
+{
+ relation_t *found = NULL, *current;
+ int i;
+
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ current = &this->relations[i];
+
+ current->lock->read_lock(current->lock);
+ if (current->subject)
+ {
+ /* check for equal issuer */
+ if (issuer->equals(issuer, current->issuer))
+ {
+ /* reuse issuer instance in cache() */
+ issuer = current->issuer;
+ if (subject->equals(subject, current->subject))
+ {
+ /* write hit counter is not locked, but not critical */
+ current->hits++;
+ found = current;
+ }
+ }
+ }
+ current->lock->unlock(current->lock);
+ if (found)
+ {
+ return TRUE;
+ }
+ }
+ /* no cache hit, check and cache signature */
+ if (subject->issued_by(subject, issuer))
+ {
+ cache(this, subject, issuer);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * certificate enumerator implemenation
+ */
+typedef struct {
+ /** implements enumerator_t interface */
+ enumerator_t public;
+ /** type of requested certificate */
+ certificate_type_t cert;
+ /** type of requested key */
+ key_type_t key;
+ /** ID to get a cert for */
+ identification_t *id;
+ /** cache */
+ relation_t *relations;
+ /** current position in array cache */
+ int index;
+ /** currently locked relation */
+ int locked;
+} cert_enumerator_t;
+
+/**
+ * filter function for certs enumerator
+ */
+static bool cert_enumerate(cert_enumerator_t *this, certificate_t **out)
+{
+ public_key_t *public;
+ relation_t *rel;
+
+ if (this->locked >= 0)
+ {
+ rel = &this->relations[this->locked];
+ rel->lock->unlock(rel->lock);
+ this->locked = -1;
+ }
+
+ while (++this->index < CACHE_SIZE)
+ {
+ rel = &this->relations[this->index];
+ rel->lock->read_lock(rel->lock);
+ this->locked = this->index;
+ if (rel->subject)
+ {
+ /* CRL lookup is done using issuer/authkeyidentifier */
+ if (this->key == KEY_ANY && this->id &&
+ (this->cert == CERT_ANY || this->cert == CERT_X509_CRL) &&
+ rel->subject->get_type(rel->subject) == CERT_X509_CRL &&
+ rel->subject->has_issuer(rel->subject, this->id))
+ {
+ *out = rel->subject;
+ return TRUE;
+ }
+ if ((this->cert == CERT_ANY ||
+ rel->subject->get_type(rel->subject) == this->cert) &&
+ (!this->id || rel->subject->has_subject(rel->subject, this->id)))
+ {
+ if (this->key == KEY_ANY)
+ {
+ *out = rel->subject;
+ return TRUE;
+ }
+ public = rel->subject->get_public_key(rel->subject);
+ if (public)
+ {
+ if (public->get_type(public) == this->key)
+ {
+ public->destroy(public);
+ *out = rel->subject;
+ return TRUE;
+ }
+ public->destroy(public);
+ }
+ }
+ }
+ this->locked = -1;
+ rel->lock->unlock(rel->lock);
+ }
+ return FALSE;
+}
+
+/**
+ * clean up enumeration data
+ */
+static void cert_enumerator_destroy(cert_enumerator_t *this)
+{
+ relation_t *rel;
+
+ if (this->locked >= 0)
+ {
+ rel = &this->relations[this->locked];
+ rel->lock->unlock(rel->lock);
+ }
+ free(this);
+}
+
+/**
+ * implementation of credential_set_t.create_cert_enumerator
+ */
+static enumerator_t *create_enumerator(private_cert_cache_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ cert_enumerator_t *enumerator;
+
+ if (trusted)
+ {
+ return NULL;
+ }
+ enumerator = malloc_thing(cert_enumerator_t);
+ enumerator->public.enumerate = (void*)cert_enumerate;
+ enumerator->public.destroy = (void*)cert_enumerator_destroy;
+ enumerator->cert = cert;
+ enumerator->key = key;
+ enumerator->id = id;
+ enumerator->relations = this->relations;
+ enumerator->index = -1;
+ enumerator->locked = -1;
+
+ return &enumerator->public;
+}
+
+/**
+ * Implementation of cert_cache_t.flush.
+ */
+static void flush(private_cert_cache_t *this, certificate_type_t type)
+{
+ relation_t *rel;
+ int i;
+
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ rel = &this->relations[i];
+ if (!rel->subject)
+ {
+ continue;
+ }
+ /* check with cheap read lock first */
+ if (type != CERT_ANY)
+ {
+ rel->lock->read_lock(rel->lock);
+ if (!rel->subject || type != rel->subject->get_type(rel->subject))
+ {
+ rel->lock->unlock(rel->lock);
+ continue;
+ }
+ rel->lock->unlock(rel->lock);
+ }
+ /* double check in write lock */
+ rel->lock->write_lock(rel->lock);
+ if (rel->subject)
+ {
+ if (type == CERT_ANY || type == rel->subject->get_type(rel->subject))
+ {
+ rel->subject->destroy(rel->subject);
+ rel->issuer->destroy(rel->issuer);
+ rel->subject = NULL;
+ rel->issuer = NULL;
+ rel->hits = 0;
+ }
+ }
+ rel->lock->unlock(rel->lock);
+ }
+}
+
+/**
+ * Implementation of cert_cache_t.destroy
+ */
+static void destroy(private_cert_cache_t *this)
+{
+ relation_t *rel;
+ int i;
+
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ rel = &this->relations[i];
+ if (rel->subject)
+ {
+ rel->subject->destroy(rel->subject);
+ rel->issuer->destroy(rel->issuer);
+ }
+ rel->lock->destroy(rel->lock);
+ }
+ free(this);
+}
+
+/*
+ * see header file
+ */
+cert_cache_t *cert_cache_create()
+{
+ private_cert_cache_t *this;
+ int i;
+
+ this = malloc_thing(private_cert_cache_t);
+ this->public.set.create_private_enumerator = (void*)return_null;
+ this->public.set.create_cert_enumerator = (void*)create_enumerator;
+ this->public.set.create_shared_enumerator = (void*)return_null;
+ this->public.set.create_cdp_enumerator = (void*)return_null;
+ this->public.set.cache_cert = (void*)nop;
+ this->public.issued_by = (bool(*)(cert_cache_t*, certificate_t *subject, certificate_t *issuer))issued_by;
+ this->public.flush = (void(*)(cert_cache_t*, certificate_type_t type))flush;
+ this->public.destroy = (void(*)(cert_cache_t*))destroy;
+
+ for (i = 0; i < CACHE_SIZE; i++)
+ {
+ this->relations[i].subject = NULL;
+ this->relations[i].issuer = NULL;
+ this->relations[i].hits = 0;
+ this->relations[i].lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
+ }
+ return &this->public;
+}
diff --git a/src/libstrongswan/credentials/sets/cert_cache.h b/src/libstrongswan/credentials/sets/cert_cache.h
new file mode 100644
index 000000000..d2721866e
--- /dev/null
+++ b/src/libstrongswan/credentials/sets/cert_cache.h
@@ -0,0 +1,71 @@
+/*
+ * 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 cert_cache cert_cache
+ * @{ @ingroup sets
+ */
+
+#ifndef CERT_CACHE_H_
+#define CERT_CACHE_H_
+
+#include <credentials/credential_set.h>
+
+typedef struct cert_cache_t cert_cache_t;
+
+/**
+ * Certificate signature verification and certificate cache.
+ *
+ * This cache serves all certificates seen in its issued_by method
+ * and serves them as untrusted through the credential set interface. Further,
+ * it caches valid subject-issuer relationships to speed up the issued_by
+ * method.
+ */
+struct cert_cache_t {
+
+ /**
+ * Implements credential_set_t.
+ */
+ credential_set_t set;
+
+ /**
+ * Caching wrapper around certificate_t.issued_by.
+ *
+ * @param subject certificate to verify
+ * @param issuer issuing certificate to verify subject
+ * @return TRUE if subject issued by issuer
+ */
+ bool (*issued_by)(cert_cache_t *this,
+ certificate_t *subject, certificate_t *issuer);
+
+ /**
+ * Flush the certificate cache.
+ *
+ * @param type type of certificate to flush, or CERT_ANY
+ */
+ void (*flush)(cert_cache_t *this, certificate_type_t type);
+
+ /**
+ * Destroy a cert_cache instance.
+ */
+ void (*destroy)(cert_cache_t *this);
+};
+
+/**
+ * Create a cert_cache instance.
+ */
+cert_cache_t *cert_cache_create();
+
+#endif /** CERT_CACHE_H_ @}*/
diff --git a/src/libstrongswan/credentials/sets/ocsp_response_wrapper.c b/src/libstrongswan/credentials/sets/ocsp_response_wrapper.c
new file mode 100644
index 000000000..4786495da
--- /dev/null
+++ b/src/libstrongswan/credentials/sets/ocsp_response_wrapper.c
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#include "ocsp_response_wrapper.h"
+
+typedef struct private_ocsp_response_wrapper_t private_ocsp_response_wrapper_t;
+
+/**
+ * private data of ocsp_response_wrapper
+ */
+struct private_ocsp_response_wrapper_t {
+
+ /**
+ * public functions
+ */
+ ocsp_response_wrapper_t public;
+
+ /**
+ * wrapped OCSP response
+ */
+ ocsp_response_t *response;
+};
+
+/**
+ * enumerator for ocsp_response_wrapper_t.create_cert_enumerator()
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** enumerator over ocsp response */
+ enumerator_t *inner;
+ /** type of cert */
+ certificate_type_t cert;
+ /** type of key */
+ key_type_t key;
+ /** filtering identity */
+ identification_t *id;
+} wrapper_enumerator_t;
+
+/**
+ * enumerate function wrapper_enumerator_t
+ */
+static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert)
+{
+ certificate_t *current;
+ public_key_t *public;
+
+ while (this->inner->enumerate(this->inner, &current))
+ {
+ if (this->cert != CERT_ANY && this->cert != current->get_type(current))
+ { /* CERT type requested, but does not match */
+ continue;
+ }
+ public = current->get_public_key(current);
+ if (this->key != KEY_ANY && !public)
+ { /* key type requested, but no public key */
+ DESTROY_IF(public);
+ continue;
+ }
+ if (this->key != KEY_ANY && public && this->key != public->get_type(public))
+ { /* key type requested, but public key has another type */
+ DESTROY_IF(public);
+ continue;
+ }
+ DESTROY_IF(public);
+ if (this->id && !current->has_subject(current, this->id))
+ { /* subject requested, but does not match */
+ continue;
+ }
+ *cert = current;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * destroy function for wrapper_enumerator_t
+ */
+static void enumerator_destroy(wrapper_enumerator_t *this)
+{
+ this->inner->destroy(this->inner);
+ free(this);
+}
+
+/**
+ * implementation of ocsp_response_wrapper_t.set.create_cert_enumerator
+ */
+static enumerator_t *create_enumerator(private_ocsp_response_wrapper_t *this,
+ certificate_type_t cert, key_type_t key,
+ identification_t *id, bool trusted)
+{
+ wrapper_enumerator_t *enumerator;
+
+ if (trusted)
+ {
+ return NULL;
+ }
+
+ enumerator = malloc_thing(wrapper_enumerator_t);
+ enumerator->cert = cert;
+ enumerator->key = key;
+ enumerator->id = id;
+ enumerator->inner = this->response->create_cert_enumerator(this->response);
+ enumerator->public.enumerate = (void*)enumerate;
+ enumerator->public.destroy = (void*)enumerator_destroy;
+ return &enumerator->public;
+}
+
+/**
+ * Implementation of ocsp_response_wrapper_t.destroy
+ */
+static void destroy(private_ocsp_response_wrapper_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response)
+{
+ private_ocsp_response_wrapper_t *this = malloc_thing(private_ocsp_response_wrapper_t);
+
+ this->public.set.create_private_enumerator = (void*)return_null;
+ this->public.set.create_cert_enumerator = (void*)create_enumerator;
+ this->public.set.create_shared_enumerator = (void*)return_null;
+ this->public.set.create_cdp_enumerator = (void*)return_null;
+ this->public.set.cache_cert = (void*)nop;
+ this->public.destroy = (void(*)(ocsp_response_wrapper_t*))destroy;
+
+ this->response = response;
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/credentials/sets/ocsp_response_wrapper.h b/src/libstrongswan/credentials/sets/ocsp_response_wrapper.h
new file mode 100644
index 000000000..dc4b451df
--- /dev/null
+++ b/src/libstrongswan/credentials/sets/ocsp_response_wrapper.h
@@ -0,0 +1,53 @@
+/*
+ * 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 ocsp_response_wrapper ocsp_response_wrapper
+ * @{ @ingroup sets
+ */
+
+#ifndef OCSP_RESPONSE_WRAPPER_H_
+#define OCSP_RESPONSE_WRAPPER_H_
+
+#include <credentials/credential_set.h>
+#include <credentials/certificates/ocsp_response.h>
+
+typedef struct ocsp_response_wrapper_t ocsp_response_wrapper_t;
+
+/**
+ * A wrapper around ocsp_response_t to handle it like a credential set.
+ */
+struct ocsp_response_wrapper_t {
+
+ /**
+ * implements credential_set_t
+ */
+ credential_set_t set;
+
+ /**
+ * Destroy a ocsp_response_wrapper instance.
+ */
+ void (*destroy)(ocsp_response_wrapper_t *this);
+};
+
+/**
+ * Create a ocsp_response_wrapper instance.
+ *
+ * @param response the wrapped OCSP response
+ * @return wrapper around response
+ */
+ocsp_response_wrapper_t *ocsp_response_wrapper_create(ocsp_response_t *response);
+
+#endif /** OCSP_RESPONSE_WRAPPER_H_ @}*/
diff --git a/src/libstrongswan/library.c b/src/libstrongswan/library.c
index 108ac2ca0..b61bdf7a0 100644
--- a/src/libstrongswan/library.c
+++ b/src/libstrongswan/library.c
@@ -18,12 +18,13 @@
#include <stdlib.h>
-#include "debug.h"
-#include "threading/thread.h"
-#include "utils/identification.h"
-#include "utils/host.h"
+#include <debug.h>
+#include <threading/thread.h>
+#include <utils/identification.h>
+#include <utils/host.h>
+#include <selectors/traffic_selector.h>
#ifdef LEAK_DETECTIVE
-#include "utils/leak_detective.h"
+#include <utils/leak_detective.h>
#endif
#define CHECKSUM_LIBRARY IPSEC_DIR"/libchecksum.so"
@@ -59,9 +60,14 @@ library_t *lib;
void library_deinit()
{
private_library_t *this = (private_library_t*)lib;
+ bool detailed;
+
+ detailed = lib->settings->get_bool(lib->settings,
+ "libstrongswan.leak_detective.detailed", TRUE);
this->public.plugins->destroy(this->public.plugins);
this->public.settings->destroy(this->public.settings);
+ this->public.credmgr->destroy(this->public.credmgr);
this->public.creds->destroy(this->public.creds);
this->public.encoding->destroy(this->public.encoding);
this->public.crypto->destroy(this->public.crypto);
@@ -76,6 +82,7 @@ void library_deinit()
#ifdef LEAK_DETECTIVE
if (this->detective)
{
+ this->detective->report(this->detective, detailed);
this->detective->destroy(this->detective);
}
#endif /* LEAK_DETECTIVE */
@@ -124,11 +131,14 @@ bool library_init(char *settings)
PRINTF_HOOK_ARGTYPE_END);
pfh->add_handler(pfh, 'Y', identification_printf_hook,
PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_END);
+ pfh->add_handler(pfh, 'R', traffic_selector_printf_hook,
+ PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_END);
this->public.settings = settings_create(settings);
this->public.crypto = crypto_factory_create();
this->public.creds = credential_factory_create();
- this->public.encoding = key_encoding_create();
+ this->public.credmgr = credential_manager_create();
+ this->public.encoding = cred_encoding_create();
this->public.fetcher = fetcher_manager_create();
this->public.db = database_factory_create();
this->public.plugins = plugin_loader_create();
diff --git a/src/libstrongswan/library.h b/src/libstrongswan/library.h
index 241084155..cd5dfb479 100644
--- a/src/libstrongswan/library.h
+++ b/src/libstrongswan/library.h
@@ -28,6 +28,9 @@
* @defgroup certificates certificates
* @ingroup credentials
*
+ * @defgroup sets sets
+ * @ingroup credentials
+ *
* @defgroup crypto crypto
* @ingroup libstrongswan
*
@@ -65,7 +68,8 @@
#include "fetcher/fetcher_manager.h"
#include "database/database_factory.h"
#include "credentials/credential_factory.h"
-#include "credentials/keys/key_encoding.h"
+#include "credentials/credential_manager.h"
+#include "credentials/cred_encoding.h"
typedef struct library_t library_t;
@@ -90,9 +94,14 @@ struct library_t {
credential_factory_t *creds;
/**
- * key encoding registry and factory
+ * Manager for the credential set backends
+ */
+ credential_manager_t *credmgr;
+
+ /**
+ * Credential encoding registry and factory
*/
- key_encoding_t *encoding;
+ cred_encoding_t *encoding;
/**
* URL fetching facility
diff --git a/src/libstrongswan/plugins/aes/Makefile.in b/src/libstrongswan/plugins/aes/Makefile.in
index 391d23049..9859b75cf 100644
--- a/src/libstrongswan/plugins/aes/Makefile.in
+++ b/src/libstrongswan/plugins/aes/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/agent/Makefile.in b/src/libstrongswan/plugins/agent/Makefile.in
index bd6465374..c95e7b778 100644
--- a/src/libstrongswan/plugins/agent/Makefile.in
+++ b/src/libstrongswan/plugins/agent/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c
index 4247f849e..51ddbecc6 100644
--- a/src/libstrongswan/plugins/agent/agent_private_key.c
+++ b/src/libstrongswan/plugins/agent/agent_private_key.c
@@ -340,7 +340,7 @@ static public_key_t* get_public_key(private_agent_private_key_t *this)
* Implementation of private_key_t.get_encoding
*/
static bool get_encoding(private_agent_private_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
return FALSE;
}
@@ -349,7 +349,7 @@ static bool get_encoding(private_agent_private_key_t *this,
* Implementation of private_key_t.get_fingerprint
*/
static bool get_fingerprint(private_agent_private_key_t *this,
- key_encoding_type_t type, chunk_t *fp)
+ cred_encoding_type_t type, chunk_t *fp)
{
chunk_t n, e, key;
@@ -363,7 +363,7 @@ static bool get_fingerprint(private_agent_private_key_t *this,
n = read_string(&key);
return lib->encoding->encode(lib->encoding, type, this, fp,
- KEY_PART_RSA_MODULUS, n, KEY_PART_RSA_PUB_EXP, e, KEY_PART_END);
+ CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
}
/**
@@ -429,9 +429,9 @@ agent_private_key_t *agent_private_key_open(key_type_t type, va_list args)
this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key;
this->public.interface.belongs_to = private_key_belongs_to;
this->public.interface.equals = private_key_equals;
- this->public.interface.get_fingerprint = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(private_key_t*, chunk_t fp))private_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref;
this->public.interface.destroy = (void (*)(private_key_t *this))destroy;
diff --git a/src/libstrongswan/plugins/blowfish/Makefile.in b/src/libstrongswan/plugins/blowfish/Makefile.in
index f95a4abe5..6a82ce94a 100644
--- a/src/libstrongswan/plugins/blowfish/Makefile.in
+++ b/src/libstrongswan/plugins/blowfish/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/curl/Makefile.in b/src/libstrongswan/plugins/curl/Makefile.in
index 1952b22e7..fc3b0ab1a 100644
--- a/src/libstrongswan/plugins/curl/Makefile.in
+++ b/src/libstrongswan/plugins/curl/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/des/Makefile.in b/src/libstrongswan/plugins/des/Makefile.in
index af351cfe3..319baa04c 100644
--- a/src/libstrongswan/plugins/des/Makefile.in
+++ b/src/libstrongswan/plugins/des/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/dnskey/Makefile.in b/src/libstrongswan/plugins/dnskey/Makefile.in
index 1f1f90127..73f81f4db 100644
--- a/src/libstrongswan/plugins/dnskey/Makefile.in
+++ b/src/libstrongswan/plugins/dnskey/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/fips_prf/Makefile.in b/src/libstrongswan/plugins/fips_prf/Makefile.in
index 70553fbd8..4ed8276c4 100644
--- a/src/libstrongswan/plugins/fips_prf/Makefile.in
+++ b/src/libstrongswan/plugins/fips_prf/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/gcrypt/Makefile.am b/src/libstrongswan/plugins/gcrypt/Makefile.am
index 48bf916ab..57f3f5016 100644
--- a/src/libstrongswan/plugins/gcrypt/Makefile.am
+++ b/src/libstrongswan/plugins/gcrypt/Makefile.am
@@ -19,4 +19,4 @@ libstrongswan_gcrypt_la_SOURCES = \
gcrypt_hasher.h gcrypt_hasher.c
libstrongswan_gcrypt_la_LDFLAGS = -module -avoid-version
-libstrongswan_gcrypt_la_LIBADD = -lgcrypt
+libstrongswan_gcrypt_la_LIBADD = -lgcrypt -lgpg-error
diff --git a/src/libstrongswan/plugins/gcrypt/Makefile.in b/src/libstrongswan/plugins/gcrypt/Makefile.in
index 35829c950..09131c4be 100644
--- a/src/libstrongswan/plugins/gcrypt/Makefile.in
+++ b/src/libstrongswan/plugins/gcrypt/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -272,7 +272,7 @@ libstrongswan_gcrypt_la_SOURCES = \
gcrypt_hasher.h gcrypt_hasher.c
libstrongswan_gcrypt_la_LDFLAGS = -module -avoid-version
-libstrongswan_gcrypt_la_LIBADD = -lgcrypt
+libstrongswan_gcrypt_la_LIBADD = -lgcrypt -lgpg-error
all: all-am
.SUFFIXES:
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
index 2cb13c5f3..b8e86aba0 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
@@ -308,7 +308,7 @@ static public_key_t* get_public_key(private_gcrypt_rsa_private_key_t *this)
* Implementation of private_key_t.get_encoding
*/
static bool get_encoding(private_gcrypt_rsa_private_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
chunk_t cn, ce, cp, cq, cd, cu, cexp1 = chunk_empty, cexp2 = chunk_empty;
gcry_mpi_t p = NULL, q = NULL, d = NULL, exp1, exp2;
@@ -368,11 +368,11 @@ static bool get_encoding(private_gcrypt_rsa_private_key_t *this,
cu = gcrypt_rsa_find_token(this->key, "u", NULL);
success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
- KEY_PART_RSA_MODULUS, cn,
- KEY_PART_RSA_PUB_EXP, ce, KEY_PART_RSA_PRIV_EXP, cd,
- KEY_PART_RSA_PRIME1, cp, KEY_PART_RSA_PRIME2, cq,
- KEY_PART_RSA_EXP1, cexp1, KEY_PART_RSA_EXP2, cexp2,
- KEY_PART_RSA_COEFF, cu, KEY_PART_END);
+ CRED_PART_RSA_MODULUS, cn,
+ CRED_PART_RSA_PUB_EXP, ce, CRED_PART_RSA_PRIV_EXP, cd,
+ CRED_PART_RSA_PRIME1, cp, CRED_PART_RSA_PRIME2, cq,
+ CRED_PART_RSA_EXP1, cexp1, CRED_PART_RSA_EXP2, cexp2,
+ CRED_PART_RSA_COEFF, cu, CRED_PART_END);
chunk_free(&cn);
chunk_free(&ce);
chunk_clear(&cd);
@@ -389,7 +389,7 @@ static bool get_encoding(private_gcrypt_rsa_private_key_t *this,
* Implementation of private_key_t.get_fingerprint
*/
static bool get_fingerprint(private_gcrypt_rsa_private_key_t *this,
- key_encoding_type_t type, chunk_t *fp)
+ cred_encoding_type_t type, chunk_t *fp)
{
chunk_t n, e;
bool success;
@@ -402,8 +402,8 @@ static bool get_fingerprint(private_gcrypt_rsa_private_key_t *this,
e = gcrypt_rsa_find_token(this->key, "e", NULL);
success = lib->encoding->encode(lib->encoding,
- type, this, fp, KEY_PART_RSA_MODULUS, n,
- KEY_PART_RSA_PUB_EXP, e, KEY_PART_END);
+ type, this, fp, CRED_PART_RSA_MODULUS, n,
+ CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
chunk_free(&n);
chunk_free(&e);
return success;
@@ -445,9 +445,9 @@ static private_gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_create_empty()
this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key;
this->public.interface.equals = private_key_equals;
this->public.interface.belongs_to = private_key_belongs_to;
- this->public.interface.get_fingerprint = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(private_key_t*, chunk_t fp))private_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref;
this->public.interface.destroy = (void (*)(private_key_t *this))destroy;
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c
index 5fd15d9a3..80a91b976 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c
@@ -240,7 +240,7 @@ static size_t get_keysize(private_gcrypt_rsa_public_key_t *this)
* Implementation of private_key_t.get_encoding
*/
static bool get_encoding(private_gcrypt_rsa_public_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
chunk_t n, e;
bool success;
@@ -248,8 +248,8 @@ static bool get_encoding(private_gcrypt_rsa_public_key_t *this,
n = gcrypt_rsa_find_token(this->key, "n", NULL);
e = gcrypt_rsa_find_token(this->key, "e", NULL);
success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
- KEY_PART_RSA_MODULUS, n, KEY_PART_RSA_PUB_EXP, e,
- KEY_PART_END);
+ CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e,
+ CRED_PART_END);
chunk_free(&n);
chunk_free(&e);
@@ -260,7 +260,7 @@ static bool get_encoding(private_gcrypt_rsa_public_key_t *this,
* Implementation of private_key_t.get_fingerprint
*/
static bool get_fingerprint(private_gcrypt_rsa_public_key_t *this,
- key_encoding_type_t type, chunk_t *fp)
+ cred_encoding_type_t type, chunk_t *fp)
{
chunk_t n, e;
bool success;
@@ -273,8 +273,8 @@ static bool get_fingerprint(private_gcrypt_rsa_public_key_t *this,
e = gcrypt_rsa_find_token(this->key, "e", NULL);
success = lib->encoding->encode(lib->encoding,
- type, this, fp, KEY_PART_RSA_MODULUS, n,
- KEY_PART_RSA_PUB_EXP, e, KEY_PART_END);
+ type, this, fp, CRED_PART_RSA_MODULUS, n,
+ CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
chunk_free(&n);
chunk_free(&e);
return success;
@@ -338,9 +338,9 @@ gcrypt_rsa_public_key_t *gcrypt_rsa_public_key_load(key_type_t type,
this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
this->public.interface.equals = public_key_equals;
this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
- this->public.interface.get_fingerprint = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(public_key_t*, chunk_t fp))public_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
diff --git a/src/libstrongswan/plugins/gmp/Makefile.in b/src/libstrongswan/plugins/gmp/Makefile.in
index 5c1a1fcd9..bd7100b27 100644
--- a/src/libstrongswan/plugins/gmp/Makefile.in
+++ b/src/libstrongswan/plugins/gmp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
index f70b0b545..cc9985320 100644
--- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
@@ -403,7 +403,7 @@ static bool belongs_to(private_gmp_rsa_private_key_t *this, public_key_t *public
* Implementation of private_key_t.get_encoding
*/
static bool get_encoding(private_gmp_rsa_private_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
chunk_t n, e, d, p, q, exp1, exp2, coeff;
bool success;
@@ -418,11 +418,11 @@ static bool get_encoding(private_gmp_rsa_private_key_t *this,
coeff = gmp_mpz_to_chunk(this->coeff);
success = lib->encoding->encode(lib->encoding,
- type, NULL, encoding, KEY_PART_RSA_MODULUS, n,
- KEY_PART_RSA_PUB_EXP, e, KEY_PART_RSA_PRIV_EXP, d,
- KEY_PART_RSA_PRIME1, p, KEY_PART_RSA_PRIME2, q,
- KEY_PART_RSA_EXP1, exp1, KEY_PART_RSA_EXP2, exp2,
- KEY_PART_RSA_COEFF, coeff, KEY_PART_END);
+ type, NULL, encoding, CRED_PART_RSA_MODULUS, n,
+ CRED_PART_RSA_PUB_EXP, e, CRED_PART_RSA_PRIV_EXP, d,
+ CRED_PART_RSA_PRIME1, p, CRED_PART_RSA_PRIME2, q,
+ CRED_PART_RSA_EXP1, exp1, CRED_PART_RSA_EXP2, exp2,
+ CRED_PART_RSA_COEFF, coeff, CRED_PART_END);
chunk_free(&n);
chunk_free(&e);
chunk_clear(&d);
@@ -439,7 +439,7 @@ static bool get_encoding(private_gmp_rsa_private_key_t *this,
* Implementation of private_key_t.get_fingerprint
*/
static bool get_fingerprint(private_gmp_rsa_private_key_t *this,
- key_encoding_type_t type, chunk_t *fp)
+ cred_encoding_type_t type, chunk_t *fp)
{
chunk_t n, e;
bool success;
@@ -452,7 +452,7 @@ static bool get_fingerprint(private_gmp_rsa_private_key_t *this,
e = gmp_mpz_to_chunk(this->e);
success = lib->encoding->encode(lib->encoding, type, this, fp,
- KEY_PART_RSA_MODULUS, n, KEY_PART_RSA_PUB_EXP, e, KEY_PART_END);
+ CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
chunk_free(&n);
chunk_free(&e);
@@ -601,9 +601,9 @@ static private_gmp_rsa_private_key_t *gmp_rsa_private_key_create_empty(void)
this->public.interface.get_public_key = (public_key_t* (*) (private_key_t*))get_public_key;
this->public.interface.equals = (bool (*) (private_key_t*, private_key_t*))equals;
this->public.interface.belongs_to = (bool (*) (private_key_t*, public_key_t*))belongs_to;
- this->public.interface.get_fingerprint = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(private_key_t*, chunk_t fp))private_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (private_key_t* (*) (private_key_t*))get_ref;
this->public.interface.destroy = (void (*) (private_key_t*))destroy;
diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
index 98dbb1922..c114ae80d 100644
--- a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
@@ -396,7 +396,7 @@ static size_t get_keysize(private_gmp_rsa_public_key_t *this)
* Implementation of public_key_t.get_encoding
*/
static bool get_encoding(private_gmp_rsa_public_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
chunk_t n, e;
bool success;
@@ -405,7 +405,7 @@ static bool get_encoding(private_gmp_rsa_public_key_t *this,
e = gmp_mpz_to_chunk(this->e);
success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
- KEY_PART_RSA_MODULUS, n, KEY_PART_RSA_PUB_EXP, e, KEY_PART_END);
+ CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
chunk_free(&n);
chunk_free(&e);
@@ -416,7 +416,7 @@ static bool get_encoding(private_gmp_rsa_public_key_t *this,
* Implementation of public_key_t.get_fingerprint
*/
static bool get_fingerprint(private_gmp_rsa_public_key_t *this,
- key_encoding_type_t type, chunk_t *fp)
+ cred_encoding_type_t type, chunk_t *fp)
{
chunk_t n, e;
bool success;
@@ -429,7 +429,7 @@ static bool get_fingerprint(private_gmp_rsa_public_key_t *this,
e = gmp_mpz_to_chunk(this->e);
success = lib->encoding->encode(lib->encoding, type, this, fp,
- KEY_PART_RSA_MODULUS, n, KEY_PART_RSA_PUB_EXP, e, KEY_PART_END);
+ CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
chunk_free(&n);
chunk_free(&e);
@@ -497,9 +497,9 @@ gmp_rsa_public_key_t *gmp_rsa_public_key_load(key_type_t type, va_list args)
this->public.interface.encrypt = (bool (*) (public_key_t*, chunk_t, chunk_t*))encrypt_;
this->public.interface.equals = (bool (*) (public_key_t*, public_key_t*))equals;
this->public.interface.get_keysize = (size_t (*) (public_key_t*))get_keysize;
- this->public.interface.get_fingerprint = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(public_key_t*, chunk_t fp))public_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (public_key_t* (*) (public_key_t *this))get_ref;
this->public.interface.destroy = (void (*) (public_key_t *this))destroy;
diff --git a/src/libstrongswan/plugins/hmac/Makefile.in b/src/libstrongswan/plugins/hmac/Makefile.in
index c965f7392..b03ff44a6 100644
--- a/src/libstrongswan/plugins/hmac/Makefile.in
+++ b/src/libstrongswan/plugins/hmac/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/ldap/Makefile.in b/src/libstrongswan/plugins/ldap/Makefile.in
index 3b69f082f..b96fd5abf 100644
--- a/src/libstrongswan/plugins/ldap/Makefile.in
+++ b/src/libstrongswan/plugins/ldap/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/md4/Makefile.in b/src/libstrongswan/plugins/md4/Makefile.in
index cb3307bbc..874ee07a2 100644
--- a/src/libstrongswan/plugins/md4/Makefile.in
+++ b/src/libstrongswan/plugins/md4/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/md5/Makefile.in b/src/libstrongswan/plugins/md5/Makefile.in
index 8948ddcc5..cc32bca88 100644
--- a/src/libstrongswan/plugins/md5/Makefile.in
+++ b/src/libstrongswan/plugins/md5/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/mysql/Makefile.in b/src/libstrongswan/plugins/mysql/Makefile.in
index 1a97c620e..83c1188b6 100644
--- a/src/libstrongswan/plugins/mysql/Makefile.in
+++ b/src/libstrongswan/plugins/mysql/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am
index a50799798..5c845a19c 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.am
+++ b/src/libstrongswan/plugins/openssl/Makefile.am
@@ -20,7 +20,9 @@ libstrongswan_openssl_la_SOURCES = \
openssl_rsa_public_key.c openssl_rsa_public_key.h \
openssl_ec_diffie_hellman.c openssl_ec_diffie_hellman.h \
openssl_ec_private_key.c openssl_ec_private_key.h \
- openssl_ec_public_key.c openssl_ec_public_key.h
+ openssl_ec_public_key.c openssl_ec_public_key.h \
+ openssl_x509.c openssl_x509.h \
+ openssl_crl.c openssl_crl.h
libstrongswan_openssl_la_LDFLAGS = -module -avoid-version
libstrongswan_openssl_la_LIBADD = -lcrypto
diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in
index a2a931d42..de9df7271 100644
--- a/src/libstrongswan/plugins/openssl/Makefile.in
+++ b/src/libstrongswan/plugins/openssl/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -79,7 +79,7 @@ am_libstrongswan_openssl_la_OBJECTS = openssl_plugin.lo \
openssl_sha1_prf.lo openssl_diffie_hellman.lo \
openssl_rsa_private_key.lo openssl_rsa_public_key.lo \
openssl_ec_diffie_hellman.lo openssl_ec_private_key.lo \
- openssl_ec_public_key.lo
+ openssl_ec_public_key.lo openssl_x509.lo openssl_crl.lo
libstrongswan_openssl_la_OBJECTS = \
$(am_libstrongswan_openssl_la_OBJECTS)
libstrongswan_openssl_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
@@ -276,7 +276,9 @@ libstrongswan_openssl_la_SOURCES = \
openssl_rsa_public_key.c openssl_rsa_public_key.h \
openssl_ec_diffie_hellman.c openssl_ec_diffie_hellman.h \
openssl_ec_private_key.c openssl_ec_private_key.h \
- openssl_ec_public_key.c openssl_ec_public_key.h
+ openssl_ec_public_key.c openssl_ec_public_key.h \
+ openssl_x509.c openssl_x509.h \
+ openssl_crl.c openssl_crl.h
libstrongswan_openssl_la_LDFLAGS = -module -avoid-version
libstrongswan_openssl_la_LIBADD = -lcrypto
@@ -363,6 +365,7 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_crl.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_crypter.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_diffie_hellman.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_ec_diffie_hellman.Plo@am__quote@
@@ -374,6 +377,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_rsa_public_key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_sha1_prf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_util.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/openssl_x509.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.c b/src/libstrongswan/plugins/openssl/openssl_crl.c
new file mode 100644
index 000000000..5645d72d7
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_crl.c
@@ -0,0 +1,530 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2010 secunet Security Networks AG
+ * Copyright (C) 2010 Thomas Egerer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "openssl_crl.h"
+#include "openssl_util.h"
+
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include <debug.h>
+#include <utils/enumerator.h>
+#include <credentials/certificates/x509.h>
+
+typedef struct private_openssl_crl_t private_openssl_crl_t;
+
+/**
+ * Private data of an openssl_crl_t object.
+ */
+struct private_openssl_crl_t {
+
+ /**
+ * Public openssl_crl_t interface.
+ */
+ openssl_crl_t public;
+
+ /**
+ * OpenSSL representation of a CRL
+ */
+ X509_CRL *crl;
+
+ /**
+ * DER encoding of the CRL
+ */
+ chunk_t encoding;
+
+ /**
+ * Serial Number (crlNumber) of the CRL)
+ */
+ chunk_t serial;
+
+ /**
+ * AuthorityKeyIdentifier of the issuing CA
+ */
+ chunk_t authKeyIdentifier;
+
+ /**
+ * Date of this CRL
+ */
+ time_t thisUpdate;
+
+ /**
+ * Date of next CRL expected
+ */
+ time_t nextUpdate;
+
+ /**
+ * Issuer of this CRL
+ */
+ identification_t *issuer;
+
+ /**
+ * Signature scheme used in this CRL
+ */
+ signature_scheme_t scheme;
+
+ /**
+ * References to this CRL
+ */
+ refcount_t ref;
+};
+
+/**
+ * Enumerator over revoked certificates
+ */
+typedef struct {
+ /**
+ * Implements enumerator_t
+ */
+ enumerator_t public;
+
+ /**
+ * stack of revoked certificates
+ */
+ STACK_OF(X509_REVOKED) *stack;
+
+ /**
+ * Total number of revoked certificates
+ */
+ int num;
+
+ /**
+ * Current position of enumerator
+ */
+ int i;
+} crl_enumerator_t;
+
+
+METHOD(enumerator_t, crl_enumerate, bool,
+ crl_enumerator_t *this, chunk_t *serial, time_t *date, crl_reason_t *reason)
+{
+ if (this->i < this->num)
+ {
+ X509_REVOKED *revoked;
+ ASN1_ENUMERATED *crlrsn;
+
+ revoked = sk_X509_REVOKED_value(this->stack, this->i);
+ if (serial)
+ {
+ *serial = openssl_asn1_str2chunk(revoked->serialNumber);
+ }
+ if (date)
+ {
+ *date = openssl_asn1_to_time(revoked->revocationDate);
+ }
+ if (reason)
+ {
+ *reason = CRL_REASON_UNSPECIFIED;
+ crlrsn = X509_REVOKED_get_ext_d2i(revoked, NID_crl_reason,
+ NULL, NULL);
+ if (crlrsn)
+ {
+ if (ASN1_STRING_type(crlrsn) == V_ASN1_ENUMERATED &&
+ ASN1_STRING_length(crlrsn) == 1)
+ {
+ *reason = *ASN1_STRING_data(crlrsn);
+ }
+ ASN1_STRING_free(crlrsn);
+ }
+ }
+ this->i++;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+METHOD(crl_t, create_enumerator, enumerator_t*,
+ private_openssl_crl_t *this)
+{
+ crl_enumerator_t *enumerator;
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_crl_enumerate,
+ .destroy = (void*)free,
+ },
+ .stack = X509_CRL_get_REVOKED(this->crl),
+ );
+ if (!enumerator->stack)
+ {
+ free(enumerator);
+ return enumerator_create_empty();
+ }
+ enumerator->num = sk_X509_EXTENSION_num(enumerator->stack);
+ return &enumerator->public;
+}
+
+METHOD(crl_t, get_serial, chunk_t,
+ private_openssl_crl_t *this)
+{
+ return this->serial;
+}
+
+METHOD(crl_t, get_authKeyIdentifier, chunk_t,
+ private_openssl_crl_t *this)
+{
+ return this->authKeyIdentifier;
+}
+
+METHOD(certificate_t, get_type, certificate_type_t,
+ private_openssl_crl_t *this)
+{
+ return CERT_X509_CRL;
+}
+
+METHOD(certificate_t, get_subject_or_issuer, identification_t*,
+ private_openssl_crl_t *this)
+{
+ return this->issuer;
+}
+
+METHOD(certificate_t, has_subject_or_issuer, id_match_t,
+ private_openssl_crl_t *this, identification_t *id)
+{
+ if (id->get_type(id) == ID_KEY_ID &&
+ chunk_equals(this->authKeyIdentifier, id->get_encoding(id)))
+ {
+ return ID_MATCH_PERFECT;
+ }
+ return this->issuer->matches(this->issuer, id);
+}
+
+METHOD(certificate_t, issued_by, bool,
+ private_openssl_crl_t *this, certificate_t *issuer)
+{
+ chunk_t fingerprint, tbs;
+ public_key_t *key;
+ x509_t *x509;
+ bool valid;
+
+ if (issuer->get_type(issuer) != CERT_X509)
+ {
+ return FALSE;
+ }
+ x509 = (x509_t*)issuer;
+ if (!(x509->get_flags(x509) & X509_CA))
+ {
+ return FALSE;
+ }
+ key = issuer->get_public_key(issuer);
+ if (!key)
+ {
+ return FALSE;
+ }
+ if (this->authKeyIdentifier.ptr && key)
+ {
+ if (!key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fingerprint) ||
+ !chunk_equals(fingerprint, this->authKeyIdentifier))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
+ {
+ return FALSE;
+ }
+ }
+ if (this->scheme == SIGN_UNKNOWN)
+ {
+ return FALSE;
+ }
+ tbs = openssl_i2chunk(X509_CRL_INFO, this->crl->crl);
+ valid = key->verify(key, this->scheme, tbs,
+ openssl_asn1_str2chunk(this->crl->signature));
+ free(tbs.ptr);
+ key->destroy(key);
+ return valid;
+}
+
+METHOD(certificate_t, get_public_key, public_key_t*,
+ private_openssl_crl_t *this)
+{
+ return NULL;
+}
+
+METHOD(certificate_t, get_validity, bool,
+ private_openssl_crl_t *this,
+ time_t *when, time_t *not_before, time_t *not_after)
+{
+ time_t t = when ? *when : time(NULL);
+
+ if (not_before)
+ {
+ *not_before = this->thisUpdate;
+ }
+ if (not_after)
+ {
+ *not_after = this->nextUpdate;
+ }
+ return t <= this->nextUpdate;
+}
+
+METHOD(certificate_t, get_encoding, bool,
+ private_openssl_crl_t *this, cred_encoding_type_t type, chunk_t *encoding)
+{
+ if (type == CERT_ASN1_DER)
+ {
+ *encoding = chunk_clone(this->encoding);
+ return TRUE;
+ }
+ return lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_X509_CRL_ASN1_DER, this->encoding, CRED_PART_END);
+}
+
+METHOD(certificate_t, equals, bool,
+ private_openssl_crl_t *this, certificate_t *other)
+{
+ chunk_t encoding;
+ bool equal;
+
+ if (&this->public.crl.certificate == other)
+ {
+ return TRUE;
+ }
+ if (other->equals == (void*)equals)
+ { /* skip allocation if we have the same implementation */
+ return chunk_equals(this->encoding,
+ ((private_openssl_crl_t*)other)->encoding);
+ }
+ if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
+ {
+ return FALSE;
+ }
+ equal = chunk_equals(this->encoding, encoding);
+ free(encoding.ptr);
+ return equal;
+}
+
+METHOD(certificate_t, get_ref, certificate_t*,
+ private_openssl_crl_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.crl.certificate;
+}
+
+METHOD(certificate_t, destroy, void,
+ private_openssl_crl_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ if (this->crl)
+ {
+ X509_CRL_free(this->crl);
+ }
+ DESTROY_IF(this->issuer);
+ free(this->authKeyIdentifier.ptr);
+ free(this->serial.ptr);
+ free(this->encoding.ptr);
+ free(this);
+ }
+}
+
+/**
+ * Create an empty CRL.
+ */
+static private_openssl_crl_t *create_empty()
+{
+ private_openssl_crl_t *this;
+
+ INIT(this,
+ .public = {
+ .crl = {
+ .certificate = {
+ .get_type = _get_type,
+ .get_subject = _get_subject_or_issuer,
+ .get_issuer = _get_subject_or_issuer,
+ .has_subject = _has_subject_or_issuer,
+ .has_issuer = _has_subject_or_issuer,
+ .issued_by = _issued_by,
+ .get_public_key = _get_public_key,
+ .get_validity = _get_validity,
+ .get_encoding = _get_encoding,
+ .equals = _equals,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_serial = _get_serial,
+ .get_authKeyIdentifier = _get_authKeyIdentifier,
+ .create_enumerator = _create_enumerator,
+ },
+ },
+ .ref = 1,
+ );
+ return this;
+}
+
+/**
+ * Parse the authKeyIdentifier extension
+ */
+static bool parse_authKeyIdentifier_ext(private_openssl_crl_t *this,
+ X509_EXTENSION *ext)
+{
+ AUTHORITY_KEYID *keyid;
+
+ keyid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext);
+ if (keyid)
+ {
+ free(this->authKeyIdentifier.ptr);
+ this->authKeyIdentifier = chunk_clone(
+ openssl_asn1_str2chunk(keyid->keyid));
+ AUTHORITY_KEYID_free(keyid);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse the crlNumber extension
+ */
+static bool parse_crlNumber_ext(private_openssl_crl_t *this,
+ X509_EXTENSION *ext)
+{
+ free(this->serial.ptr);
+ this->serial = chunk_clone(
+ openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext)));
+ return this->serial.len != 0;
+}
+
+/**
+ * Parse X509 CRL extensions
+ */
+static bool parse_extensions(private_openssl_crl_t *this)
+{
+ bool ok;
+ int i, num;
+ X509_EXTENSION *ext;
+ STACK_OF(X509_EXTENSION) *extensions;
+
+ extensions = this->crl->crl->extensions;
+ if (extensions)
+ {
+ num = sk_X509_EXTENSION_num(extensions);
+ for (i = 0; i < num; ++i)
+ {
+ ext = sk_X509_EXTENSION_value(extensions, i);
+
+ switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext)))
+ {
+ case NID_authority_key_identifier:
+ ok = parse_authKeyIdentifier_ext(this, ext);
+ break;
+ case NID_crl_number:
+ ok = parse_crlNumber_ext(this, ext);
+ break;
+ default:
+ ok = TRUE;
+ break;
+ }
+ if (!ok)
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Parse a X509 CRL
+ */
+static bool parse_crl(private_openssl_crl_t *this)
+{
+ const unsigned char *ptr = this->encoding.ptr;
+
+ this->crl = d2i_X509_CRL(NULL, &ptr, this->encoding.len);
+ if (!this->crl)
+ {
+ return FALSE;
+ }
+
+ if (!chunk_equals(
+ openssl_asn1_obj2chunk(this->crl->crl->sig_alg->algorithm),
+ openssl_asn1_obj2chunk(this->crl->sig_alg->algorithm)))
+ {
+ return FALSE;
+ }
+ this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(
+ this->crl->sig_alg->algorithm));
+
+ this->issuer = openssl_x509_name2id(X509_CRL_get_issuer(this->crl));
+ if (!this->issuer)
+ {
+ return FALSE;
+ }
+ this->thisUpdate = openssl_asn1_to_time(X509_CRL_get_lastUpdate(this->crl));
+ this->nextUpdate = openssl_asn1_to_time(X509_CRL_get_nextUpdate(this->crl));
+
+ return parse_extensions(this);
+}
+
+/**
+ * Load the CRL.
+ */
+openssl_crl_t *openssl_crl_load(certificate_type_t type, va_list args)
+{
+ chunk_t blob = chunk_empty;
+
+ while (TRUE)
+ {
+ switch (va_arg(args, builder_part_t))
+ {
+ case BUILD_BLOB_ASN1_DER:
+ blob = va_arg(args, chunk_t);
+ continue;
+ case BUILD_END:
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ }
+ if (blob.ptr)
+ {
+ private_openssl_crl_t *this = create_empty();
+
+ this->encoding = chunk_clone(blob);
+ if (parse_crl(this))
+ {
+ return &this->public;
+ }
+ destroy(this);
+ }
+ return NULL;
+}
diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.h b/src/libstrongswan/plugins/openssl/openssl_crl.h
new file mode 100644
index 000000000..a0837cf50
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_crl.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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 openssl_crl openssl_crl
+ * @{ @ingroup openssl_p
+ */
+
+#ifndef OPENSSL_CRL_H_
+#define OPENSSL_CRL_H_
+
+typedef struct openssl_crl_t openssl_crl_t;
+
+#include <credentials/certificates/crl.h>
+
+/**
+ * X.509 Certificate Revocation list implemented with OpenSSL.
+ */
+struct openssl_crl_t {
+
+ /**
+ * Implements the crl_t interface.
+ */
+ crl_t crl;
+};
+
+/**
+ * Load a X.509 CRL using OpenSSL.
+ *
+ * @param type certificate type, CERT_X509_CRL only
+ * @param args builder_part_t argument list
+ * @return X.509 CRL, NULL on failure
+ */
+openssl_crl_t *openssl_crl_load(certificate_type_t type, va_list args);
+
+#endif /** OPENSSL_CRL_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
index faec411cd..a53e8aea0 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
@@ -13,6 +13,10 @@
* for more details.
*/
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_EC
+
#include <openssl/ec.h>
#include <openssl/objects.h>
@@ -331,3 +335,5 @@ openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(diffie_hellman_gro
return &this->public;
}
+#endif /* OPENSSL_NO_EC */
+
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c
index bdcfda974..281155913 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c
@@ -14,6 +14,10 @@
* for more details.
*/
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_EC
+
#include "openssl_ec_private_key.h"
#include "openssl_ec_public_key.h"
#include "openssl_util.h"
@@ -47,7 +51,7 @@ struct private_openssl_ec_private_key_t {
};
/* from ec public key */
-bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp);
+bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp);
/**
* Build a signature as in RFC 4754
@@ -217,7 +221,7 @@ static public_key_t* get_public_key(private_openssl_ec_private_key_t *this)
* Implementation of private_key_t.get_fingerprint.
*/
static bool get_fingerprint(private_openssl_ec_private_key_t *this,
- key_encoding_type_t type, chunk_t *fingerprint)
+ cred_encoding_type_t type, chunk_t *fingerprint)
{
return openssl_ec_fingerprint(this->ec, type, fingerprint);
}
@@ -226,14 +230,14 @@ static bool get_fingerprint(private_openssl_ec_private_key_t *this,
* Implementation of private_key_t.get_encoding.
*/
static bool get_encoding(private_openssl_ec_private_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
u_char *p;
switch (type)
{
- case KEY_PRIV_ASN1_DER:
- case KEY_PRIV_PEM:
+ case PRIVKEY_ASN1_DER:
+ case PRIVKEY_PEM:
{
bool success = TRUE;
@@ -241,13 +245,13 @@ static bool get_encoding(private_openssl_ec_private_key_t *this,
p = encoding->ptr;
i2d_ECPrivateKey(this->ec, &p);
- if (type == KEY_PRIV_PEM)
+ if (type == PRIVKEY_PEM)
{
chunk_t asn1_encoding = *encoding;
- success = lib->encoding->encode(lib->encoding, KEY_PRIV_PEM,
- NULL, encoding, KEY_PART_ECDSA_PRIV_ASN1_DER,
- asn1_encoding, KEY_PART_END);
+ success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
+ NULL, encoding, CRED_PART_ECDSA_PRIV_ASN1_DER,
+ asn1_encoding, CRED_PART_END);
chunk_clear(&asn1_encoding);
}
return success;
@@ -296,9 +300,9 @@ static private_openssl_ec_private_key_t *create_empty(void)
this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key;
this->public.interface.equals = private_key_equals;
this->public.interface.belongs_to = private_key_belongs_to;
- this->public.interface.get_fingerprint = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(private_key_t*, chunk_t fp))private_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref;
this->public.interface.destroy = (void (*)(private_key_t *this))destroy;
@@ -402,4 +406,5 @@ openssl_ec_private_key_t *openssl_ec_private_key_load(key_type_t type,
}
return &this->public;
}
+#endif /* OPENSSL_NO_EC */
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
index 790a8487d..def36c92f 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
@@ -14,6 +14,10 @@
* for more details.
*/
+#include <openssl/opensslconf.h>
+
+#ifndef OPENSSL_NO_EC
+
#include "openssl_ec_public_key.h"
#include "openssl_util.h"
@@ -189,7 +193,7 @@ static size_t get_keysize(private_openssl_ec_public_key_t *this)
/**
* Calculate fingerprint from a EC_KEY, also used in ec private key.
*/
-bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp)
+bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp)
{
hasher_t *hasher;
chunk_t key;
@@ -201,12 +205,12 @@ bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp)
}
switch (type)
{
- case KEY_ID_PUBKEY_SHA1:
+ case KEYID_PUBKEY_SHA1:
key = chunk_alloc(i2o_ECPublicKey(ec, NULL));
p = key.ptr;
i2o_ECPublicKey(ec, &p);
break;
- case KEY_ID_PUBKEY_INFO_SHA1:
+ case KEYID_PUBKEY_INFO_SHA1:
key = chunk_alloc(i2d_EC_PUBKEY(ec, NULL));
p = key.ptr;
i2d_EC_PUBKEY(ec, &p);
@@ -232,7 +236,7 @@ bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp)
* Implementation of private_key_t.get_fingerprint.
*/
static bool get_fingerprint(private_openssl_ec_public_key_t *this,
- key_encoding_type_t type, chunk_t *fingerprint)
+ cred_encoding_type_t type, chunk_t *fingerprint)
{
return openssl_ec_fingerprint(this->ec, type, fingerprint);
}
@@ -241,14 +245,14 @@ static bool get_fingerprint(private_openssl_ec_public_key_t *this,
* Implementation of private_key_t.get_encoding.
*/
static bool get_encoding(private_openssl_ec_public_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
u_char *p;
switch (type)
{
- case KEY_PUB_SPKI_ASN1_DER:
- case KEY_PUB_PEM:
+ case PUBKEY_SPKI_ASN1_DER:
+ case PUBKEY_PEM:
{
bool success = TRUE;
@@ -256,13 +260,13 @@ static bool get_encoding(private_openssl_ec_public_key_t *this,
p = encoding->ptr;
i2d_EC_PUBKEY(this->ec, &p);
- if (type == KEY_PUB_PEM)
+ if (type == PUBKEY_PEM)
{
chunk_t asn1_encoding = *encoding;
- success = lib->encoding->encode(lib->encoding, KEY_PUB_PEM,
- NULL, encoding, KEY_PART_ECDSA_PUB_ASN1_DER,
- asn1_encoding, KEY_PART_END);
+ success = lib->encoding->encode(lib->encoding, PUBKEY_PEM,
+ NULL, encoding, CRED_PART_ECDSA_PUB_ASN1_DER,
+ asn1_encoding, CRED_PART_END);
chunk_clear(&asn1_encoding);
}
return success;
@@ -309,9 +313,9 @@ static private_openssl_ec_public_key_t *create_empty()
this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
this->public.interface.equals = public_key_equals;
- this->public.interface.get_fingerprint = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(public_key_t*, chunk_t fp))public_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
@@ -358,4 +362,5 @@ openssl_ec_public_key_t *openssl_ec_public_key_load(key_type_t type,
}
return &this->public;
}
+#endif /* OPENSSL_NO_EC */
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index c1545ffb8..31697dcb8 100644
--- a/src/libstrongswan/plugins/openssl/openssl_plugin.c
+++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c
@@ -14,10 +14,12 @@
* for more details.
*/
-#include <openssl/conf.h>
#include <openssl/evp.h>
-#include <openssl/engine.h>
+#include <openssl/conf.h>
#include <openssl/crypto.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
#include "openssl_plugin.h"
@@ -34,6 +36,8 @@
#include "openssl_rsa_public_key.h"
#include "openssl_ec_private_key.h"
#include "openssl_ec_public_key.h"
+#include "openssl_x509.h"
+#include "openssl_crl.h"
typedef struct private_openssl_plugin_t private_openssl_plugin_t;
@@ -175,8 +179,6 @@ static void destroy(private_openssl_plugin_t *this)
(prf_constructor_t)openssl_sha1_prf_create);
lib->crypto->remove_dh(lib->crypto,
(dh_constructor_t)openssl_diffie_hellman_create);
- lib->crypto->remove_dh(lib->crypto,
- (dh_constructor_t)openssl_ec_diffie_hellman_create);
lib->creds->remove_builder(lib->creds,
(builder_function_t)openssl_rsa_private_key_load);
lib->creds->remove_builder(lib->creds,
@@ -185,14 +187,24 @@ static void destroy(private_openssl_plugin_t *this)
(builder_function_t)openssl_rsa_private_key_connect);
lib->creds->remove_builder(lib->creds,
(builder_function_t)openssl_rsa_public_key_load);
+#ifndef OPENSSL_NO_EC
+ lib->crypto->remove_dh(lib->crypto,
+ (dh_constructor_t)openssl_ec_diffie_hellman_create);
lib->creds->remove_builder(lib->creds,
(builder_function_t)openssl_ec_private_key_load);
lib->creds->remove_builder(lib->creds,
(builder_function_t)openssl_ec_private_key_gen);
lib->creds->remove_builder(lib->creds,
(builder_function_t)openssl_ec_public_key_load);
+#endif /* OPENSSL_NO_EC */
+ lib->creds->remove_builder(lib->creds,
+ (builder_function_t)openssl_x509_load);
+ lib->creds->remove_builder(lib->creds,
+ (builder_function_t)openssl_crl_load);
+#ifndef OPENSSL_NO_ENGINE
ENGINE_cleanup();
+#endif /* OPENSSL_NO_ENGINE */
EVP_cleanup();
CONF_modules_free();
@@ -215,9 +227,11 @@ plugin_t *openssl_plugin_create()
OPENSSL_config(NULL);
OpenSSL_add_all_algorithms();
+#ifndef OPENSSL_NO_ENGINE
/* activate support for hardware accelerators */
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
+#endif /* OPENSSL_NO_ENGINE */
/* crypter */
lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC,
@@ -272,6 +286,7 @@ plugin_t *openssl_plugin_create()
(dh_constructor_t)openssl_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, MODP_1536_BIT,
(dh_constructor_t)openssl_diffie_hellman_create);
+#ifndef OPENSSL_NO_EC
lib->crypto->add_dh(lib->crypto, ECP_256_BIT,
(dh_constructor_t)openssl_ec_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, ECP_384_BIT,
@@ -282,6 +297,7 @@ plugin_t *openssl_plugin_create()
(dh_constructor_t)openssl_ec_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, ECP_192_BIT,
(dh_constructor_t)openssl_ec_diffie_hellman_create);
+#endif /* OPENSSL_NO_EC */
lib->crypto->add_dh(lib->crypto, MODP_3072_BIT,
(dh_constructor_t)openssl_diffie_hellman_create);
lib->crypto->add_dh(lib->crypto, MODP_4096_BIT,
@@ -306,14 +322,24 @@ plugin_t *openssl_plugin_create()
(builder_function_t)openssl_rsa_private_key_connect);
lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
(builder_function_t)openssl_rsa_public_key_load);
+ lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
+ (builder_function_t)openssl_rsa_public_key_load);
- /* ec */
+#ifndef OPENSSL_NO_EC
+ /* ecdsa */
lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
(builder_function_t)openssl_ec_private_key_load);
lib->creds->add_builder(lib->creds, CRED_PRIVATE_KEY, KEY_ECDSA,
(builder_function_t)openssl_ec_private_key_gen);
lib->creds->add_builder(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
(builder_function_t)openssl_ec_public_key_load);
+#endif /* OPENSSL_NO_EC */
+
+ /* X509 certificates */
+ lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ (builder_function_t)openssl_x509_load);
+ lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
+ (builder_function_t)openssl_crl_load);
return &this->public.plugin;
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
index de751fe89..5817ade9e 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c
@@ -21,7 +21,9 @@
#include <openssl/evp.h>
#include <openssl/rsa.h>
+#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
+#endif /* OPENSSL_NO_ENGINE */
/**
* Public exponent to use for key generation.
@@ -56,7 +58,7 @@ struct private_openssl_rsa_private_key_t {
};
/* implemented in rsa public key */
-bool openssl_rsa_fingerprint(RSA *rsa, key_encoding_type_t type, chunk_t *fp);
+bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp);
/**
* Build an EMPSA PKCS1 signature described in PKCS#1
@@ -206,7 +208,7 @@ static public_key_t* get_public_key(private_openssl_rsa_private_key_t *this)
* Implementation of public_key_t.get_fingerprint.
*/
static bool get_fingerprint(private_openssl_rsa_private_key_t *this,
- key_encoding_type_t type, chunk_t *fingerprint)
+ cred_encoding_type_t type, chunk_t *fingerprint)
{
return openssl_rsa_fingerprint(this->rsa, type, fingerprint);
}
@@ -215,7 +217,7 @@ static bool get_fingerprint(private_openssl_rsa_private_key_t *this,
* Implementation of public_key_t.get_encoding.
*/
static bool get_encoding(private_openssl_rsa_private_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
u_char *p;
@@ -225,8 +227,8 @@ static bool get_encoding(private_openssl_rsa_private_key_t *this,
}
switch (type)
{
- case KEY_PRIV_ASN1_DER:
- case KEY_PRIV_PEM:
+ case PRIVKEY_ASN1_DER:
+ case PRIVKEY_PEM:
{
bool success = TRUE;
@@ -234,13 +236,13 @@ static bool get_encoding(private_openssl_rsa_private_key_t *this,
p = encoding->ptr;
i2d_RSAPrivateKey(this->rsa, &p);
- if (type == KEY_PRIV_PEM)
+ if (type == PRIVKEY_PEM)
{
chunk_t asn1_encoding = *encoding;
- success = lib->encoding->encode(lib->encoding, KEY_PRIV_PEM,
- NULL, encoding, KEY_PART_RSA_PRIV_ASN1_DER,
- asn1_encoding, KEY_PART_END);
+ success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
+ NULL, encoding, CRED_PART_RSA_PRIV_ASN1_DER,
+ asn1_encoding, CRED_PART_END);
chunk_clear(&asn1_encoding);
}
return success;
@@ -289,9 +291,9 @@ static private_openssl_rsa_private_key_t *create_empty(void)
this->public.interface.get_public_key = (public_key_t* (*) (private_key_t*))get_public_key;
this->public.interface.equals = private_key_equals;
this->public.interface.belongs_to = private_key_belongs_to;
- this->public.interface.get_fingerprint = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(private_key_t*, chunk_t fp))private_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(private_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (private_key_t* (*) (private_key_t*))get_ref;
this->public.interface.destroy = (void (*) (private_key_t*))destroy;
@@ -447,6 +449,7 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type,
openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
va_list args)
{
+#ifndef OPENSSL_NO_ENGINE
private_openssl_rsa_private_key_t *this;
char *keyid = NULL, *pin = NULL;
EVP_PKEY *key;
@@ -511,5 +514,8 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type,
this->engine = TRUE;
return &this->public;
+#else /* OPENSSL_NO_ENGINE */
+ return NULL;
+#endif /* OPENSSL_NO_ENGINE */
}
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
index ffa575a97..6ac61a65c 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
@@ -172,7 +172,7 @@ static size_t get_keysize(private_openssl_rsa_public_key_t *this)
/**
* Calculate fingerprint from a RSA key, also used in rsa private key.
*/
-bool openssl_rsa_fingerprint(RSA *rsa, key_encoding_type_t type, chunk_t *fp)
+bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp)
{
hasher_t *hasher;
chunk_t key;
@@ -184,12 +184,12 @@ bool openssl_rsa_fingerprint(RSA *rsa, key_encoding_type_t type, chunk_t *fp)
}
switch (type)
{
- case KEY_ID_PUBKEY_SHA1:
+ case KEYID_PUBKEY_SHA1:
key = chunk_alloc(i2d_RSAPublicKey(rsa, NULL));
p = key.ptr;
i2d_RSAPublicKey(rsa, &p);
break;
- case KEY_ID_PUBKEY_INFO_SHA1:
+ case KEYID_PUBKEY_INFO_SHA1:
key = chunk_alloc(i2d_RSA_PUBKEY(rsa, NULL));
p = key.ptr;
i2d_RSA_PUBKEY(rsa, &p);
@@ -215,7 +215,7 @@ bool openssl_rsa_fingerprint(RSA *rsa, key_encoding_type_t type, chunk_t *fp)
* Implementation of public_key_t.get_fingerprint.
*/
static bool get_fingerprint(private_openssl_rsa_public_key_t *this,
- key_encoding_type_t type, chunk_t *fingerprint)
+ cred_encoding_type_t type, chunk_t *fingerprint)
{
return openssl_rsa_fingerprint(this->rsa, type, fingerprint);
}
@@ -224,14 +224,14 @@ static bool get_fingerprint(private_openssl_rsa_public_key_t *this,
* Implementation of public_key_t.get_encoding.
*/
static bool get_encoding(private_openssl_rsa_public_key_t *this,
- key_encoding_type_t type, chunk_t *encoding)
+ cred_encoding_type_t type, chunk_t *encoding)
{
u_char *p;
switch (type)
{
- case KEY_PUB_SPKI_ASN1_DER:
- case KEY_PUB_PEM:
+ case PUBKEY_SPKI_ASN1_DER:
+ case PUBKEY_PEM:
{
bool success = TRUE;
@@ -239,18 +239,18 @@ static bool get_encoding(private_openssl_rsa_public_key_t *this,
p = encoding->ptr;
i2d_RSA_PUBKEY(this->rsa, &p);
- if (type == KEY_PUB_PEM)
+ if (type == PUBKEY_PEM)
{
chunk_t asn1_encoding = *encoding;
- success = lib->encoding->encode(lib->encoding, KEY_PUB_PEM,
- NULL, encoding, KEY_PART_RSA_PUB_ASN1_DER,
- asn1_encoding, KEY_PART_END);
+ success = lib->encoding->encode(lib->encoding, PUBKEY_PEM,
+ NULL, encoding, CRED_PART_RSA_PUB_ASN1_DER,
+ asn1_encoding, CRED_PART_END);
chunk_clear(&asn1_encoding);
}
return success;
}
- case KEY_PUB_ASN1_DER:
+ case PUBKEY_ASN1_DER:
{
*encoding = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL));
p = encoding->ptr;
@@ -299,9 +299,9 @@ static private_openssl_rsa_public_key_t *create_empty()
this->public.interface.encrypt = (bool (*)(public_key_t *this, chunk_t crypto, chunk_t *plain))encrypt_;
this->public.interface.equals = public_key_equals;
this->public.interface.get_keysize = (size_t (*) (public_key_t *this))get_keysize;
- this->public.interface.get_fingerprint = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
+ this->public.interface.get_fingerprint = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *fp))get_fingerprint;
this->public.interface.has_fingerprint = (bool(*)(public_key_t*, chunk_t fp))public_key_has_fingerprint;
- this->public.interface.get_encoding = (bool(*)(public_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
+ this->public.interface.get_encoding = (bool(*)(public_key_t*, cred_encoding_type_t type, chunk_t *encoding))get_encoding;
this->public.interface.get_ref = (public_key_t* (*)(public_key_t *this))get_ref;
this->public.interface.destroy = (void (*)(public_key_t *this))destroy;
@@ -345,13 +345,25 @@ openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type,
this = create_empty();
if (blob.ptr)
{
- this->rsa = d2i_RSAPublicKey(NULL, (const u_char**)&blob.ptr, blob.len);
+ switch (type)
+ {
+ case KEY_ANY:
+ this->rsa = d2i_RSA_PUBKEY(NULL, (const u_char**)&blob.ptr,
+ blob.len);
+ break;
+ case KEY_RSA:
+ this->rsa = d2i_RSAPublicKey(NULL, (const u_char**)&blob.ptr,
+ blob.len);
+ break;
+ default:
+ break;
+ }
if (this->rsa)
{
return &this->public;
}
}
- else if (n.ptr && e.ptr)
+ else if (n.ptr && e.ptr && type == KEY_RSA)
{
this->rsa = RSA_new();
this->rsa->n = BN_bin2bn((const u_char*)n.ptr, n.len, NULL);
diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h
index 9a24e7ee1..384e328e2 100644
--- a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h
+++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.h
@@ -15,7 +15,7 @@
/**
* @defgroup openssl_sha1_prf openssl_sha1_prf
- * @{ @ingroup sha1_p
+ * @{ @ingroup openssl_p
*/
#ifndef OPENSSL_SHA1_PRF_H_
diff --git a/src/libstrongswan/plugins/openssl/openssl_util.c b/src/libstrongswan/plugins/openssl/openssl_util.c
index 55b18a524..99dca3631 100644
--- a/src/libstrongswan/plugins/openssl/openssl_util.c
+++ b/src/libstrongswan/plugins/openssl/openssl_util.c
@@ -100,7 +100,6 @@ error:
return FALSE;
}
-
/**
* Described in header.
*/
@@ -124,3 +123,85 @@ bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b)
return TRUE;
}
+/**
+ * Described in header.
+ */
+chunk_t openssl_asn1_obj2chunk(ASN1_OBJECT *asn1)
+{
+ if (asn1)
+ {
+ return chunk_create(asn1->data, asn1->length);
+ }
+ return chunk_empty;
+}
+
+/**
+ * Described in header.
+ */
+chunk_t openssl_asn1_str2chunk(ASN1_STRING *asn1)
+{
+ if (asn1)
+ {
+ return chunk_create(ASN1_STRING_data(asn1), ASN1_STRING_length(asn1));
+ }
+ return chunk_empty;
+}
+
+/**
+ * Convert a X509 name to a ID_DER_ASN1_DN identification_t
+ */
+identification_t *openssl_x509_name2id(X509_NAME *name)
+{
+ if (name)
+ {
+ identification_t *id;
+ chunk_t chunk;
+
+ chunk = openssl_i2chunk(X509_NAME, name);
+ if (chunk.len)
+ {
+ id = identification_create_from_encoding(ID_DER_ASN1_DN, chunk);
+ free(chunk.ptr);
+ return id;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * We can't include <asn1/asn1.h>, as the ASN1_ definitions would clash
+ * with OpenSSL. Redeclare what we need.
+ */
+int asn1_known_oid(chunk_t);
+time_t asn1_to_time(chunk_t *,int);
+
+/**
+ * Described in header.
+ */
+int openssl_asn1_known_oid(ASN1_OBJECT *obj)
+{
+ return asn1_known_oid(openssl_asn1_obj2chunk(obj));
+}
+
+/**
+ * Described in header.
+ */
+time_t openssl_asn1_to_time(ASN1_TIME *time)
+{
+ chunk_t chunk;
+
+ if (time)
+ {
+ chunk = openssl_asn1_str2chunk(time);
+ switch (time->type)
+ {
+ case V_ASN1_UTCTIME:
+ case V_ASN1_GENERALIZEDTIME:
+ return asn1_to_time(&chunk, time->type);
+ default:
+ break;
+ }
+ }
+ DBG1(DBG_LIB, "invalid ASN1 time");
+ return 0;
+}
diff --git a/src/libstrongswan/plugins/openssl/openssl_util.h b/src/libstrongswan/plugins/openssl/openssl_util.h
index 538008f2c..25c692a1a 100644
--- a/src/libstrongswan/plugins/openssl/openssl_util.h
+++ b/src/libstrongswan/plugins/openssl/openssl_util.h
@@ -23,6 +23,7 @@
#include <library.h>
#include <openssl/bn.h>
+#include <openssl/asn1.h>
/**
* Returns the length in bytes of a field element
@@ -37,7 +38,7 @@
* @param hash_type NID of the hash
* @param data the chunk of data to hash
* @param hash chunk that contains the hash
- * @return TRUE on success, FALSE otherwise
+ * @return TRUE on success, FALSE otherwise
*/
bool openssl_hash_chunk(int hash_type, chunk_t data, chunk_t *hash);
@@ -65,4 +66,57 @@ bool openssl_bn_cat(int len, BIGNUM *a, BIGNUM *b, chunk_t *chunk);
*/
bool openssl_bn_split(chunk_t chunk, BIGNUM *a, BIGNUM *b);
+
+/**
+ * Allocate a chunk using the i2d function of a given object
+ *
+ * @param type type of the object
+ * @param obj object to convert to DER
+ * @returns allocated chunk of the object, or chunk_empty
+ */
+#define openssl_i2chunk(type, obj) ({ \
+ unsigned char *ptr = NULL; \
+ int len = i2d_##type(obj, &ptr); \
+ len < 0 ? chunk_empty : chunk_create(ptr, len);})
+
+/**
+ * Convert an OpenSSL ASN1_OBJECT to a chunk.
+ *
+ * @param asn1 asn1 object to convert
+ * @return chunk, pointing into asn1 object
+ */
+chunk_t openssl_asn1_obj2chunk(ASN1_OBJECT *asn1);
+
+/**
+ * Convert an OpenSSL ASN1_STRING to a chunk.
+ *
+ * @param asn1 asn1 string to convert
+ * @return chunk, pointing into asn1 string
+ */
+chunk_t openssl_asn1_str2chunk(ASN1_STRING *asn1);
+
+/**
+ * Convert an openssl X509_NAME to a identification_t of type ID_DER_ASN1_DN.
+ *
+ * @param name name to convert
+ * @return identification_t, NULL on error
+ */
+identification_t *openssl_x509_name2id(X509_NAME *name);
+
+/**
+ * Check if an ASN1 oid is a an OID known by libstrongswan.
+ *
+ * @param obj openssl ASN1 object
+ * @returns OID, as defined in <asn1/oid.h>
+ */
+int openssl_asn1_known_oid(ASN1_OBJECT *obj);
+
+/**
+ * Convert an OpenSSL ASN1_TIME to a time_t.
+ *
+ * @param time openssl ASN1_TIME
+ * @returns time_t, 0 on error
+ */
+time_t openssl_asn1_to_time(ASN1_TIME *time);
+
#endif /** OPENSSL_UTIL_H_ @}*/
diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c
new file mode 100644
index 000000000..1c9bb699e
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_x509.c
@@ -0,0 +1,871 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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.
+ */
+
+/*
+ * Copyright (C) 2010 secunet Security Networks AG
+ * Copyright (C) 2010 Thomas Egerer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "openssl_x509.h"
+#include "openssl_util.h"
+
+#include <debug.h>
+#include <asn1/oid.h>
+#include <utils/linked_list.h>
+
+
+typedef struct private_openssl_x509_t private_openssl_x509_t;
+
+/**
+ * Private data of an openssl_x509_t object.
+ */
+struct private_openssl_x509_t {
+
+ /**
+ * Public openssl_x509_t interface.
+ */
+ openssl_x509_t public;
+
+ /**
+ * OpenSSL certificate representation
+ */
+ X509 *x509;
+
+ /**
+ * DER encoded certificate
+ */
+ chunk_t encoding;
+
+ /**
+ * SHA1 hash of the certificate
+ */
+ chunk_t hash;
+
+ /**
+ * X509 flags
+ */
+ x509_flag_t flags;
+
+ /**
+ * Pathlen constraint
+ */
+ int pathlen;
+
+ /**
+ * certificate subject
+ */
+ identification_t *subject;
+
+ /**
+ * certificate issuer
+ */
+ identification_t *issuer;
+
+ /**
+ * Certificates public key
+ */
+ public_key_t *pubkey;
+
+ /**
+ * subjectKeyIdentifier as read from cert
+ */
+ chunk_t subjectKeyIdentifier;
+
+ /**
+ * authorityKeyIdentifier as read from cert
+ */
+ chunk_t authKeyIdentifier;
+
+ /**
+ * Start time of certificate validity
+ */
+ time_t notBefore;
+
+ /**
+ * End time of certificate validity
+ */
+ time_t notAfter;
+
+ /**
+ * Signature scheme of the certificate
+ */
+ signature_scheme_t scheme;
+
+ /**
+ * subjectAltNames
+ */
+ linked_list_t *subjectAltNames;
+
+ /**
+ * issuerAltNames
+ */
+ linked_list_t *issuerAltNames;
+
+ /**
+ * List of CRL URIs
+ */
+ linked_list_t *crl_uris;
+
+ /**
+ * List of OCSP URIs
+ */
+ linked_list_t *ocsp_uris;
+
+ /**
+ * References to this cert
+ */
+ refcount_t ref;
+};
+
+/**
+ * Convert a GeneralName to an identification_t.
+ */
+static identification_t *general_name2id(GENERAL_NAME *name)
+{
+ if (!name)
+ {
+ return NULL;
+ }
+ switch (name->type)
+ {
+ case GEN_EMAIL:
+ return identification_create_from_encoding(ID_RFC822_ADDR,
+ openssl_asn1_str2chunk(name->d.rfc822Name));
+ case GEN_DNS:
+ return identification_create_from_encoding(ID_FQDN,
+ openssl_asn1_str2chunk(name->d.dNSName));
+ case GEN_URI:
+ return identification_create_from_encoding(ID_DER_ASN1_GN_URI,
+ openssl_asn1_str2chunk(name->d.uniformResourceIdentifier));
+ case GEN_IPADD:
+ {
+ chunk_t chunk = openssl_asn1_str2chunk(name->d.iPAddress);
+ if (chunk.len == 4)
+ {
+ return identification_create_from_encoding(ID_IPV4_ADDR, chunk);
+ }
+ if (chunk.len == 16)
+ {
+ return identification_create_from_encoding(ID_IPV6_ADDR, chunk);
+ }
+ return NULL;
+ }
+ case GEN_DIRNAME :
+ return openssl_x509_name2id(name->d.directoryName);
+ default:
+ return NULL;
+ }
+}
+
+METHOD(x509_t, get_flags, x509_flag_t,
+ private_openssl_x509_t *this)
+{
+ return this->flags;
+}
+
+METHOD(x509_t, get_serial, chunk_t,
+ private_openssl_x509_t *this)
+{
+ return openssl_asn1_str2chunk(X509_get_serialNumber(this->x509));
+}
+
+METHOD(x509_t, get_subjectKeyIdentifier, chunk_t,
+ private_openssl_x509_t *this)
+{
+ chunk_t fingerprint;
+
+ if (this->subjectKeyIdentifier.len)
+ {
+ return this->subjectKeyIdentifier;
+ }
+ if (this->pubkey->get_fingerprint(this->pubkey, KEYID_PUBKEY_SHA1,
+ &fingerprint))
+ {
+ return fingerprint;
+ }
+ return chunk_empty;
+}
+
+METHOD(x509_t, get_authKeyIdentifier, chunk_t,
+ private_openssl_x509_t *this)
+{
+ if (this->authKeyIdentifier.len)
+ {
+ return this->authKeyIdentifier;
+ }
+ return chunk_empty;
+}
+
+METHOD(x509_t, get_pathLenConstraint, int,
+ private_openssl_x509_t *this)
+{
+ return this->pathlen;
+}
+
+METHOD(x509_t, create_subjectAltName_enumerator, enumerator_t*,
+ private_openssl_x509_t *this)
+{
+ return this->subjectAltNames->create_enumerator(this->subjectAltNames);
+}
+
+METHOD(x509_t, create_crl_uri_enumerator, enumerator_t*,
+ private_openssl_x509_t *this)
+{
+ return this->crl_uris->create_enumerator(this->crl_uris);
+}
+
+METHOD(x509_t, create_ocsp_uri_enumerator, enumerator_t*,
+ private_openssl_x509_t *this)
+{
+ return this->ocsp_uris->create_enumerator(this->ocsp_uris);
+}
+
+METHOD(x509_t, create_ipAddrBlock_enumerator, enumerator_t*,
+ private_openssl_x509_t *this)
+{
+ /* TODO */
+ return enumerator_create_empty();
+}
+
+METHOD(certificate_t, get_type, certificate_type_t,
+ private_openssl_x509_t *this)
+{
+ return CERT_X509;
+}
+
+METHOD(certificate_t, get_subject, identification_t*,
+ private_openssl_x509_t *this)
+{
+ return this->subject;
+}
+
+METHOD(certificate_t, get_issuer, identification_t*,
+ private_openssl_x509_t *this)
+{
+ return this->issuer;
+}
+
+METHOD(certificate_t, has_subject, id_match_t,
+ private_openssl_x509_t *this, identification_t *subject)
+{
+ identification_t *current;
+ enumerator_t *enumerator;
+ id_match_t match, best;
+
+ if (subject->get_type(subject) == ID_KEY_ID)
+ {
+ if (chunk_equals(this->hash, subject->get_encoding(subject)))
+ {
+ return ID_MATCH_PERFECT;
+ }
+ }
+ best = this->subject->matches(this->subject, subject);
+ enumerator = create_subjectAltName_enumerator(this);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ match = current->matches(current, subject);
+ if (match > best)
+ {
+ best = match;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return best;
+}
+
+METHOD(certificate_t, has_issuer, id_match_t,
+ private_openssl_x509_t *this, identification_t *issuer)
+{
+ /* issuerAltNames currently not supported */
+ return this->issuer->matches(this->issuer, issuer);
+}
+
+METHOD(certificate_t, issued_by, bool,
+ private_openssl_x509_t *this, certificate_t *issuer)
+{
+ public_key_t *key;
+ bool valid;
+ x509_t *x509 = (x509_t*)issuer;
+ chunk_t tbs;
+
+ if (&this->public.x509.interface == issuer)
+ {
+ if (this->flags & X509_SELF_SIGNED)
+ {
+ return TRUE;
+ }
+ }
+ else
+ {
+ if (issuer->get_type(issuer) != CERT_X509)
+ {
+ return FALSE;
+ }
+ if (!(x509->get_flags(x509) & X509_CA))
+ {
+ return FALSE;
+ }
+ if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
+ {
+ return FALSE;
+ }
+ }
+ if (this->scheme == SIGN_UNKNOWN)
+ {
+ return FALSE;
+ }
+ key = issuer->get_public_key(issuer);
+ if (!key)
+ {
+ return FALSE;
+ }
+ tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info);
+ valid = key->verify(key, this->scheme, tbs,
+ openssl_asn1_str2chunk(this->x509->signature));
+ free(tbs.ptr);
+ key->destroy(key);
+ return valid;
+}
+
+METHOD(certificate_t, get_public_key, public_key_t*,
+ private_openssl_x509_t *this)
+{
+ return this->pubkey->get_ref(this->pubkey);
+}
+
+METHOD(certificate_t, get_validity, bool,
+ private_openssl_x509_t *this,
+ time_t *when, time_t *not_before, time_t *not_after)
+{
+ time_t t;
+
+ if (when)
+ {
+ t = *when;
+ }
+ else
+ {
+ t = time(NULL);
+ }
+ if (not_before)
+ {
+ *not_before = this->notBefore;
+ }
+ if (not_after)
+ {
+ *not_after = this->notAfter;
+ }
+ return (t >= this->notBefore && t <= this->notAfter);
+}
+
+METHOD(certificate_t, get_encoding, bool,
+ private_openssl_x509_t *this, cred_encoding_type_t type, chunk_t *encoding)
+{
+ if (type == CERT_ASN1_DER)
+ {
+ *encoding = chunk_clone(this->encoding);
+ return TRUE;
+ }
+ return lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_X509_ASN1_DER, this->encoding, CRED_PART_END);
+}
+
+
+METHOD(certificate_t, equals, bool,
+ private_openssl_x509_t *this, certificate_t *other)
+{
+ chunk_t encoding;
+ bool equal;
+
+ if (this == (private_openssl_x509_t*)other)
+ {
+ return TRUE;
+ }
+ if (other->get_type(other) != CERT_X509)
+ {
+ return FALSE;
+ }
+ if (other->equals == (void*)equals)
+ { /* skip allocation if we have the same implementation */
+ encoding = ((private_openssl_x509_t*)other)->encoding;
+ return chunk_equals(this->encoding, encoding);
+ }
+ if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
+ {
+ return FALSE;
+ }
+ equal = chunk_equals(this->encoding, encoding);
+ free(encoding.ptr);
+ return equal;
+}
+
+METHOD(certificate_t, get_ref, certificate_t*,
+ private_openssl_x509_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.x509.interface;
+}
+
+METHOD(certificate_t, destroy, void,
+ private_openssl_x509_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ if (this->x509)
+ {
+ X509_free(this->x509);
+ }
+ DESTROY_IF(this->subject);
+ DESTROY_IF(this->issuer);
+ DESTROY_IF(this->pubkey);
+ free(this->subjectKeyIdentifier.ptr);
+ free(this->authKeyIdentifier.ptr);
+ free(this->encoding.ptr);
+ free(this->hash.ptr);
+ this->subjectAltNames->destroy_offset(this->subjectAltNames,
+ offsetof(identification_t, destroy));
+ this->issuerAltNames->destroy_offset(this->issuerAltNames,
+ offsetof(identification_t, destroy));
+ this->crl_uris->destroy_function(this->crl_uris, free);
+ this->ocsp_uris->destroy_function(this->ocsp_uris, free);
+ free(this);
+ }
+}
+
+/**
+ * Create an empty certificate
+ */
+static private_openssl_x509_t *create_empty()
+{
+ private_openssl_x509_t *this;
+
+ INIT(this,
+ .public = {
+ .x509 = {
+ .interface = {
+ .get_type = _get_type,
+ .get_subject = _get_subject,
+ .get_issuer = _get_issuer,
+ .has_subject = _has_subject,
+ .has_issuer = _has_issuer,
+ .issued_by = _issued_by,
+ .get_public_key = _get_public_key,
+ .get_validity = _get_validity,
+ .get_encoding = _get_encoding,
+ .equals = _equals,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_flags = _get_flags,
+ .get_serial = _get_serial,
+ .get_subjectKeyIdentifier = _get_subjectKeyIdentifier,
+ .get_authKeyIdentifier = _get_authKeyIdentifier,
+ .get_pathLenConstraint = _get_pathLenConstraint,
+ .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
+ .create_crl_uri_enumerator = _create_crl_uri_enumerator,
+ .create_ocsp_uri_enumerator = _create_ocsp_uri_enumerator,
+ .create_ipAddrBlock_enumerator = _create_ipAddrBlock_enumerator,
+ },
+ },
+ .subjectAltNames = linked_list_create(),
+ .issuerAltNames = linked_list_create(),
+ .crl_uris = linked_list_create(),
+ .ocsp_uris = linked_list_create(),
+ .pathlen = X509_NO_PATH_LEN_CONSTRAINT,
+ .ref = 1,
+ );
+
+ return this;
+}
+
+/**
+ * parse an extionsion containing GENERAL_NAMES into a list
+ */
+static bool parse_generalNames_ext(linked_list_t *list,
+ X509_EXTENSION *ext)
+{
+ GENERAL_NAMES *names;
+ GENERAL_NAME *name;
+ identification_t *id;
+ int i, num;
+
+ names = X509V3_EXT_d2i(ext);
+ if (!names)
+ {
+ return FALSE;
+ }
+
+ num = sk_GENERAL_NAME_num(names);
+ for (i = 0; i < num; i++)
+ {
+ name = sk_GENERAL_NAME_value(names, i);
+ id = general_name2id(name);
+ if (id)
+ {
+ list->insert_last(list, id);
+ }
+ GENERAL_NAME_free(name);
+ }
+ sk_GENERAL_NAME_free(names);
+ return TRUE;
+}
+
+/**
+ * parse basic constraints
+ */
+static bool parse_basicConstraints_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ BASIC_CONSTRAINTS *constraints;
+
+ constraints = (BASIC_CONSTRAINTS*)X509V3_EXT_d2i(ext);
+ if (constraints)
+ {
+ if (constraints->ca)
+ {
+ this->flags |= X509_CA;
+ }
+ if (constraints->pathlen)
+ {
+ this->pathlen = ASN1_INTEGER_get(constraints->pathlen);
+ }
+ BASIC_CONSTRAINTS_free(constraints);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse CRL distribution points
+ */
+static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ CRL_DIST_POINTS *cdps;
+ DIST_POINT *cdp;
+ identification_t *id;
+ char *uri;
+ int i, j, point_num, name_num;
+
+ cdps = X509V3_EXT_d2i(ext);
+ if (!cdps)
+ {
+ return FALSE;
+ }
+ point_num = sk_DIST_POINT_num(cdps);
+ for (i = 0; i < point_num; i++)
+ {
+ cdp = sk_DIST_POINT_value(cdps, i);
+ if (cdp)
+ {
+ if (cdp->distpoint && cdp->distpoint->type == 0 &&
+ cdp->distpoint->name.fullname)
+ {
+ name_num = sk_GENERAL_NAME_num(cdp->distpoint->name.fullname);
+ for (j = 0; j < name_num; j++)
+ {
+ id = general_name2id(sk_GENERAL_NAME_value(
+ cdp->distpoint->name.fullname, j));
+ if (id)
+ {
+ if (asprintf(&uri, "%Y", id) > 0)
+ {
+ this->crl_uris->insert_first(this->crl_uris, uri);
+ }
+ id->destroy(id);
+ }
+ }
+ }
+ DIST_POINT_free(cdp);
+ }
+ }
+ sk_DIST_POINT_free(cdps);
+ return TRUE;
+}
+
+/**
+ * Parse authorityInfoAccess with OCSP URIs
+ */
+static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ AUTHORITY_INFO_ACCESS *infos;
+ ACCESS_DESCRIPTION *desc;
+ identification_t *id;
+ int i, num;
+ char *uri;
+
+ infos = X509V3_EXT_d2i(ext);
+ if (!infos)
+ {
+ return FALSE;
+ }
+ num = sk_ACCESS_DESCRIPTION_num(infos);
+ for (i = 0; i < num; i++)
+ {
+ desc = sk_ACCESS_DESCRIPTION_value(infos, i);
+ if (desc)
+ {
+ if (openssl_asn1_known_oid(desc->method) == OID_OCSP)
+ {
+ id = general_name2id(desc->location);
+ if (id)
+ {
+ if (asprintf(&uri, "%Y", id) > 0)
+ {
+ this->ocsp_uris->insert_first(this->ocsp_uris, uri);
+ }
+ id->destroy(id);
+ }
+ }
+ ACCESS_DESCRIPTION_free(desc);
+ }
+ }
+ sk_ACCESS_DESCRIPTION_free(infos);
+ return TRUE;
+}
+
+/**
+ * Parse authorityKeyIdentifier extension
+ */
+static bool parse_authKeyIdentifier_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ AUTHORITY_KEYID *keyid;
+
+ keyid = (AUTHORITY_KEYID*)X509V3_EXT_d2i(ext);
+ if (keyid)
+ {
+ free(this->authKeyIdentifier.ptr);
+ this->authKeyIdentifier = chunk_clone(
+ openssl_asn1_str2chunk(keyid->keyid));
+ AUTHORITY_KEYID_free(keyid);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse subjectKeyIdentifier extension
+ */
+static bool parse_subjectKeyIdentifier_ext(private_openssl_x509_t *this,
+ X509_EXTENSION *ext)
+{
+ chunk_t ostr;
+
+ ostr = openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext));
+ /* quick and dirty unwrap of octet string */
+ if (ostr.len > 2 &&
+ ostr.ptr[0] == V_ASN1_OCTET_STRING && ostr.ptr[1] == ostr.len - 2)
+ {
+ free(this->subjectKeyIdentifier.ptr);
+ this->subjectKeyIdentifier = chunk_clone(chunk_skip(ostr, 2));
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Parse X509 extensions we are interested in
+ */
+static bool parse_extensions(private_openssl_x509_t *this)
+{
+ STACK_OF(X509_EXTENSION) *extensions;
+ int i, num;
+
+ extensions = this->x509->cert_info->extensions;
+ if (extensions)
+ {
+ num = sk_X509_EXTENSION_num(extensions);
+
+ for (i = 0; i < num; i++)
+ {
+ X509_EXTENSION *ext;
+ bool ok;
+
+ ext = sk_X509_EXTENSION_value(extensions, i);
+ switch (OBJ_obj2nid(X509_EXTENSION_get_object(ext)))
+ {
+ case NID_info_access:
+ ok = parse_authorityInfoAccess_ext(this, ext);
+ break;
+ case NID_authority_key_identifier:
+ ok = parse_authKeyIdentifier_ext(this, ext);
+ break;
+ case NID_subject_key_identifier:
+ ok = parse_subjectKeyIdentifier_ext(this, ext);
+ break;
+ case NID_subject_alt_name:
+ ok = parse_generalNames_ext(this->subjectAltNames, ext);
+ break;
+ case NID_issuer_alt_name:
+ ok = parse_generalNames_ext(this->issuerAltNames, ext);
+ break;
+ case NID_basic_constraints:
+ ok = parse_basicConstraints_ext(this, ext);
+ break;
+ case NID_crl_distribution_points:
+ ok = parse_crlDistributionPoints_ext(this, ext);
+ break;
+ default:
+ ok = TRUE;
+ break;
+ }
+ if (!ok)
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/**
+ * Parse a DER encoded x509 certificate
+ */
+static bool parse_certificate(private_openssl_x509_t *this)
+{
+ const unsigned char *ptr = this->encoding.ptr;
+ hasher_t *hasher;
+ chunk_t chunk;
+
+ this->x509 = d2i_X509(NULL, &ptr, this->encoding.len);
+ if (!this->x509)
+ {
+ return FALSE;
+ }
+ this->subject = openssl_x509_name2id(X509_get_subject_name(this->x509));
+ this->issuer = openssl_x509_name2id(X509_get_issuer_name(this->x509));
+
+ switch (openssl_asn1_known_oid(this->x509->cert_info->key->algor->algorithm))
+ {
+ case OID_RSA_ENCRYPTION:
+ this->pubkey = lib->creds->create(lib->creds,
+ CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_ASN1_DER,
+ openssl_asn1_str2chunk(X509_get0_pubkey_bitstr(this->x509)),
+ BUILD_END);
+ break;
+ case OID_EC_PUBLICKEY:
+ /* for ECDSA, we need the full subjectPublicKeyInfo, as it contains
+ * the curve parameters. */
+ chunk = openssl_i2chunk(X509_PUBKEY, X509_get_X509_PUBKEY(this->x509));
+ this->pubkey = lib->creds->create(lib->creds,
+ CRED_PUBLIC_KEY, KEY_ECDSA, BUILD_BLOB_ASN1_DER,
+ chunk, BUILD_END);
+ free(chunk.ptr);
+ break;
+ default:
+ DBG1(DBG_LIB, "unsupported public key algorithm");
+ break;
+ }
+ if (!this->subject || !this->issuer || !this->pubkey)
+ {
+ return FALSE;
+ }
+
+ this->notBefore = openssl_asn1_to_time(X509_get_notBefore(this->x509));
+ this->notAfter = openssl_asn1_to_time(X509_get_notAfter(this->x509));
+
+ if (!chunk_equals(
+ openssl_asn1_obj2chunk(this->x509->cert_info->signature->algorithm),
+ openssl_asn1_obj2chunk(this->x509->sig_alg->algorithm)))
+ {
+ return FALSE;
+ }
+ this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(
+ this->x509->sig_alg->algorithm));
+
+ if (!parse_extensions(this))
+ {
+ return TRUE;
+ }
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (!hasher)
+ {
+ return FALSE;
+ }
+ hasher->allocate_hash(hasher, this->encoding, &this->hash);
+ hasher->destroy(hasher);
+
+ if (issued_by(this, &this->public.x509.interface))
+ {
+ this->flags |= X509_SELF_SIGNED;
+ }
+ return TRUE;
+}
+
+openssl_x509_t *openssl_x509_load(certificate_type_t type, va_list args)
+{
+ chunk_t blob = chunk_empty;
+ x509_flag_t flags = 0;
+
+ while (TRUE)
+ {
+ switch (va_arg(args, builder_part_t))
+ {
+ case BUILD_BLOB_ASN1_DER:
+ blob = va_arg(args, chunk_t);
+ continue;
+ case BUILD_X509_FLAG:
+ flags |= va_arg(args, x509_flag_t);
+ continue;
+ case BUILD_END:
+ break;
+ default:
+ return NULL;
+ }
+ break;
+ }
+
+ if (blob.ptr)
+ {
+ private_openssl_x509_t *this;
+
+ this = create_empty();
+ this->encoding = chunk_clone(blob);
+ this->flags |= flags;
+ if (parse_certificate(this))
+ {
+ return &this->public;
+ }
+ DBG1(DBG_LIB, "OpenSSL X.509 parsing failed");
+ destroy(this);
+ }
+ return NULL;
+}
diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.h b/src/libstrongswan/plugins/openssl/openssl_x509.h
new file mode 100644
index 000000000..52555925a
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_x509.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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 openssl_x509 openssl_x509
+ * @{ @ingroup openssl_p
+ */
+
+#ifndef OPENSSL_X509_H_
+#define OPENSSL_X509_H_
+
+#include <credentials/certificates/x509.h>
+
+typedef struct openssl_x509_t openssl_x509_t;
+
+/**
+ * X.509 certificate implementation using OpenSSL.
+ */
+struct openssl_x509_t {
+
+ /**
+ * Implements x509_t interface.
+ */
+ x509_t x509;
+};
+
+/**
+ * Load a X.509 certificate.
+ *
+ * This function takes a BUILD_BLOB_ASN1_DER.
+ *
+ * @param type certificate type, CERT_X509 only
+ * @param args builder_part_t argument list
+ * @return X.509 certificate, NULL on failure
+ */
+openssl_x509_t *openssl_x509_load(certificate_type_t type, va_list args);
+
+#endif /** OPENSSL_X509_H_ @}*/
diff --git a/src/libstrongswan/plugins/padlock/Makefile.in b/src/libstrongswan/plugins/padlock/Makefile.in
index 84c2ef2fb..adb8f08d1 100644
--- a/src/libstrongswan/plugins/padlock/Makefile.in
+++ b/src/libstrongswan/plugins/padlock/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/pem/Makefile.in b/src/libstrongswan/plugins/pem/Makefile.in
index 4e39c8f7b..e19a66fa5 100644
--- a/src/libstrongswan/plugins/pem/Makefile.in
+++ b/src/libstrongswan/plugins/pem/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/pem/pem_builder.c b/src/libstrongswan/plugins/pem/pem_builder.c
index 65be9501b..a15c3f258 100644
--- a/src/libstrongswan/plugins/pem/pem_builder.c
+++ b/src/libstrongswan/plugins/pem/pem_builder.c
@@ -528,7 +528,7 @@ static void *pem_load(credential_type_t type, int subtype, va_list args)
break;
}
- if (pem.ptr)
+ if (pem.len)
{
return load_from_blob(pem, type, subtype, cb, cb_data, flags);
}
diff --git a/src/libstrongswan/plugins/pem/pem_encoder.c b/src/libstrongswan/plugins/pem/pem_encoder.c
index 13c99a958..e255d6fd0 100644
--- a/src/libstrongswan/plugins/pem/pem_encoder.c
+++ b/src/libstrongswan/plugins/pem/pem_encoder.c
@@ -20,7 +20,7 @@
/**
* See header.
*/
-bool pem_encoder_encode(key_encoding_type_t type, chunk_t *encoding,
+bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
va_list args)
{
chunk_t asn1;
@@ -31,62 +31,81 @@ bool pem_encoder_encode(key_encoding_type_t type, chunk_t *encoding,
switch (type)
{
- case KEY_PUB_PEM:
+ case PUBKEY_PEM:
label ="PUBLIC KEY";
/* direct PKCS#1 PEM encoding */
- if (key_encoding_args(args, KEY_PART_RSA_PUB_ASN1_DER,
- &asn1, KEY_PART_END) ||
- key_encoding_args(args, KEY_PART_ECDSA_PUB_ASN1_DER,
- &asn1, KEY_PART_END))
+ if (cred_encoding_args(args, CRED_PART_RSA_PUB_ASN1_DER,
+ &asn1, CRED_PART_END) ||
+ cred_encoding_args(args, CRED_PART_ECDSA_PUB_ASN1_DER,
+ &asn1, CRED_PART_END))
{
break;
}
/* indirect PEM encoding from components */
- if (key_encoding_args(args, KEY_PART_RSA_MODULUS, &n,
- KEY_PART_RSA_PUB_EXP, &e, KEY_PART_END))
+ if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n,
+ CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END))
{
- if (lib->encoding->encode(lib->encoding, KEY_PUB_SPKI_ASN1_DER,
- NULL, &asn1, KEY_PART_RSA_MODULUS, n,
- KEY_PART_RSA_PUB_EXP, e, KEY_PART_END))
+ if (lib->encoding->encode(lib->encoding, PUBKEY_SPKI_ASN1_DER,
+ NULL, &asn1, CRED_PART_RSA_MODULUS, n,
+ CRED_PART_RSA_PUB_EXP, e, CRED_PART_END))
{
to_free = asn1;
break;
}
}
return FALSE;
- case KEY_PRIV_PEM:
+ case PRIVKEY_PEM:
label ="RSA PRIVATE KEY";
/* direct PKCS#1 PEM encoding */
- if (key_encoding_args(args, KEY_PART_RSA_PRIV_ASN1_DER,
- &asn1, KEY_PART_END))
+ if (cred_encoding_args(args, CRED_PART_RSA_PRIV_ASN1_DER,
+ &asn1, CRED_PART_END))
{
break;
}
/* indirect PEM encoding from components */
- if (key_encoding_args(args, KEY_PART_RSA_MODULUS, &n,
- KEY_PART_RSA_PUB_EXP, &e, KEY_PART_RSA_PRIV_EXP, &d,
- KEY_PART_RSA_PRIME1, &p, KEY_PART_RSA_PRIME2, &q,
- KEY_PART_RSA_EXP1, &exp1, KEY_PART_RSA_EXP2, &exp2,
- KEY_PART_RSA_COEFF, &coeff, KEY_PART_END))
+ if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n,
+ CRED_PART_RSA_PUB_EXP, &e, CRED_PART_RSA_PRIV_EXP, &d,
+ CRED_PART_RSA_PRIME1, &p, CRED_PART_RSA_PRIME2, &q,
+ CRED_PART_RSA_EXP1, &exp1, CRED_PART_RSA_EXP2, &exp2,
+ CRED_PART_RSA_COEFF, &coeff, CRED_PART_END))
{
- if (lib->encoding->encode(lib->encoding, KEY_PRIV_ASN1_DER, NULL,
- &asn1, KEY_PART_RSA_MODULUS, n,
- KEY_PART_RSA_PUB_EXP, e, KEY_PART_RSA_PRIV_EXP, d,
- KEY_PART_RSA_PRIME1, p, KEY_PART_RSA_PRIME2, q,
- KEY_PART_RSA_EXP1, exp1, KEY_PART_RSA_EXP2, exp2,
- KEY_PART_RSA_COEFF, coeff, KEY_PART_END))
+ if (lib->encoding->encode(lib->encoding, PRIVKEY_ASN1_DER, NULL,
+ &asn1, CRED_PART_RSA_MODULUS, n,
+ CRED_PART_RSA_PUB_EXP, e, CRED_PART_RSA_PRIV_EXP, d,
+ CRED_PART_RSA_PRIME1, p, CRED_PART_RSA_PRIME2, q,
+ CRED_PART_RSA_EXP1, exp1, CRED_PART_RSA_EXP2, exp2,
+ CRED_PART_RSA_COEFF, coeff, CRED_PART_END))
{
to_free = asn1;
break;
}
}
- if (key_encoding_args(args, KEY_PART_ECDSA_PRIV_ASN1_DER,
- &asn1, KEY_PART_END))
+ if (cred_encoding_args(args, CRED_PART_ECDSA_PRIV_ASN1_DER,
+ &asn1, CRED_PART_END))
{
label ="EC PRIVATE KEY";
break;
}
return FALSE;
+ case CERT_PEM:
+ if (cred_encoding_args(args, CRED_PART_X509_ASN1_DER,
+ &asn1, CRED_PART_END))
+ { /* PEM encode x509 certificate */
+ label = "CERTIFICATE";
+ break;
+ }
+ if (cred_encoding_args(args, CRED_PART_X509_CRL_ASN1_DER,
+ &asn1, CRED_PART_END))
+ { /* PEM encode CRL */
+ label = "X509 CRL";
+ break;
+ }
+ if (cred_encoding_args(args, CRED_PART_PKCS10_ASN1_DER,
+ &asn1, CRED_PART_END))
+ { /* PEM encode PKCS10 certificate reqeuest */
+ label = "CERTIFICATE REQUEST";
+ break;
+ }
default:
return FALSE;
}
diff --git a/src/libstrongswan/plugins/pem/pem_encoder.h b/src/libstrongswan/plugins/pem/pem_encoder.h
index a181133b7..d8f05dd73 100644
--- a/src/libstrongswan/plugins/pem/pem_encoder.h
+++ b/src/libstrongswan/plugins/pem/pem_encoder.h
@@ -21,12 +21,12 @@
#ifndef PEM_ENCODER_H_
#define PEM_ENCODER_H_
-#include <credentials/keys/key_encoding.h>
+#include <credentials/cred_encoding.h>
/**
* Encoding from ASN.1 to PEM format.
*/
-bool pem_encoder_encode(key_encoding_type_t type, chunk_t *encoding,
+bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
va_list args);
#endif /** PEM_ENCODER_H_ @}*/
diff --git a/src/libstrongswan/plugins/pgp/Makefile.in b/src/libstrongswan/plugins/pgp/Makefile.in
index 5d487364f..a5bc5eb39 100644
--- a/src/libstrongswan/plugins/pgp/Makefile.in
+++ b/src/libstrongswan/plugins/pgp/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/pgp/pgp_cert.c b/src/libstrongswan/plugins/pgp/pgp_cert.c
index cd04f3d1a..5b21b46d4 100644
--- a/src/libstrongswan/plugins/pgp/pgp_cert.c
+++ b/src/libstrongswan/plugins/pgp/pgp_cert.c
@@ -188,28 +188,18 @@ static bool get_validity(private_pgp_cert_t *this, time_t *when,
}
/**
- * Implementation of certificate_t.is_newer.
- */
-static bool is_newer(certificate_t *this, certificate_t *that)
-{
- time_t this_update, that_update, now = time(NULL);
- bool new;
-
- this->get_validity(this, &now, &this_update, NULL);
- that->get_validity(that, &now, &that_update, NULL);
- new = this_update > that_update;
- DBG1(DBG_LIB, " certificate from %T is %s - existing certificate"
- " from %T %s", &this_update, FALSE, new ? "newer" : "not newer",
- &that_update, FALSE, new ? "replaced" : "retained");
- return new;
-}
-
-/**
* Implementation of certificate_t.get_encoding.
*/
-static chunk_t get_encoding(private_pgp_cert_t *this)
+static bool get_encoding(private_pgp_cert_t *this, cred_encoding_type_t type,
+ chunk_t *encoding)
{
- return chunk_clone(this->encoding);
+ if (type == CERT_PGP_PKT)
+ {
+ *encoding = chunk_clone(this->encoding);
+ return TRUE;
+ }
+ return lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_PGP_CERT, this->encoding, CRED_PART_END);
}
/**
@@ -232,7 +222,10 @@ static bool equals(private_pgp_cert_t *this, certificate_t *other)
{ /* skip allocation if we have the same implementation */
return chunk_equals(this->encoding, ((private_pgp_cert_t*)other)->encoding);
}
- encoding = other->get_encoding(other);
+ if (!other->get_encoding(other, CERT_PGP_PKT, &encoding))
+ {
+ return FALSE;
+ }
equal = chunk_equals(this->encoding, encoding);
free(encoding.ptr);
return equal;
@@ -276,8 +269,7 @@ private_pgp_cert_t *create_empty()
this->public.interface.interface.issued_by = (bool (*) (certificate_t*, certificate_t*))issued_by;
this->public.interface.interface.get_public_key = (public_key_t* (*) (certificate_t*))get_public_key;
this->public.interface.interface.get_validity = (bool (*) (certificate_t*, time_t*, time_t*, time_t*))get_validity;
- this->public.interface.interface.is_newer = (bool (*) (certificate_t*,certificate_t*))is_newer;
- this->public.interface.interface.get_encoding = (chunk_t (*) (certificate_t*))get_encoding;
+ this->public.interface.interface.get_encoding = (bool (*) (certificate_t*,cred_encoding_type_t,chunk_t*))get_encoding;
this->public.interface.interface.equals = (bool (*)(certificate_t*, certificate_t*))equals;
this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t*))get_ref;
this->public.interface.interface.destroy = (void (*)(certificate_t*))destroy;
@@ -365,7 +357,7 @@ static bool parse_public_key(private_pgp_cert_t *this, chunk_t packet)
else
{
/* V3 fingerprint is computed by public_key_t class */
- if (!this->key->get_fingerprint(this->key, KEY_ID_PGPV3,
+ if (!this->key->get_fingerprint(this->key, KEYID_PGPV3,
&this->fingerprint))
{
return FALSE;
diff --git a/src/libstrongswan/plugins/pgp/pgp_encoder.c b/src/libstrongswan/plugins/pgp/pgp_encoder.c
index d5c3df590..9043cdb9f 100644
--- a/src/libstrongswan/plugins/pgp/pgp_encoder.c
+++ b/src/libstrongswan/plugins/pgp/pgp_encoder.c
@@ -25,8 +25,8 @@ static bool build_v3_fingerprint(chunk_t *encoding, va_list args)
hasher_t *hasher;
chunk_t n, e;
- if (key_encoding_args(args, KEY_PART_RSA_MODULUS, &n,
- KEY_PART_RSA_PUB_EXP, &e, KEY_PART_END))
+ if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n,
+ CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END))
{
hasher = lib->crypto->create_hasher(lib->crypto, HASH_MD5);
if (!hasher)
@@ -55,12 +55,12 @@ static bool build_v3_fingerprint(chunk_t *encoding, va_list args)
/**
* See header.
*/
-bool pgp_encoder_encode(key_encoding_type_t type, chunk_t *encoding,
- va_list args)
+bool pgp_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
+ va_list args)
{
switch (type)
{
- case KEY_ID_PGPV3:
+ case KEYID_PGPV3:
return build_v3_fingerprint(encoding, args);
default:
return FALSE;
diff --git a/src/libstrongswan/plugins/pgp/pgp_encoder.h b/src/libstrongswan/plugins/pgp/pgp_encoder.h
index 9df143399..b5bc2af44 100644
--- a/src/libstrongswan/plugins/pgp/pgp_encoder.h
+++ b/src/libstrongswan/plugins/pgp/pgp_encoder.h
@@ -21,12 +21,12 @@
#ifndef PGP_ENCODER_H_
#define PGP_ENCODER_H_
-#include <credentials/keys/key_encoding.h>
+#include <credentials/cred_encoding.h>
/**
* Encoding function for PGP fingerprints.
*/
-bool pgp_encoder_encode(key_encoding_type_t type, chunk_t *encoding,
+bool pgp_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
va_list args);
#endif /** PGP_ENCODER_H_ @}*/
diff --git a/src/libstrongswan/plugins/pkcs1/Makefile.in b/src/libstrongswan/plugins/pkcs1/Makefile.in
index 3fdcd0590..947f52d82 100644
--- a/src/libstrongswan/plugins/pkcs1/Makefile.in
+++ b/src/libstrongswan/plugins/pkcs1/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c b/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
index e46062d97..6957b2ad1 100644
--- a/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
+++ b/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.c
@@ -26,8 +26,8 @@ bool build_pub(chunk_t *encoding, va_list args)
{
chunk_t n, e;
- if (key_encoding_args(args, KEY_PART_RSA_MODULUS, &n,
- KEY_PART_RSA_PUB_EXP, &e, KEY_PART_END))
+ if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n,
+ CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END))
{
*encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_wrap(ASN1_INTEGER, "c", n),
@@ -44,8 +44,8 @@ bool build_pub_info(chunk_t *encoding, va_list args)
{
chunk_t n, e;
- if (key_encoding_args(args, KEY_PART_RSA_MODULUS, &n,
- KEY_PART_RSA_PUB_EXP, &e, KEY_PART_END))
+ if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n,
+ CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END))
{
*encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
@@ -65,11 +65,11 @@ bool build_priv(chunk_t *encoding, va_list args)
{
chunk_t n, e, d, p, q, exp1, exp2, coeff;
- if (key_encoding_args(args, KEY_PART_RSA_MODULUS, &n,
- KEY_PART_RSA_PUB_EXP, &e, KEY_PART_RSA_PRIV_EXP, &d,
- KEY_PART_RSA_PRIME1, &p, KEY_PART_RSA_PRIME2, &q,
- KEY_PART_RSA_EXP1, &exp1, KEY_PART_RSA_EXP2, &exp2,
- KEY_PART_RSA_COEFF, &coeff, KEY_PART_END))
+ if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n,
+ CRED_PART_RSA_PUB_EXP, &e, CRED_PART_RSA_PRIV_EXP, &d,
+ CRED_PART_RSA_PRIME1, &p, CRED_PART_RSA_PRIME2, &q,
+ CRED_PART_RSA_EXP1, &exp1, CRED_PART_RSA_EXP2, &exp2,
+ CRED_PART_RSA_COEFF, &coeff, CRED_PART_END))
{
*encoding = asn1_wrap(ASN1_SEQUENCE, "cmmssssss",
ASN1_INTEGER_0,
@@ -138,20 +138,20 @@ static bool build_sha1(chunk_t *encoding, va_list args)
/**
* See header.
*/
-bool pkcs1_encoder_encode(key_encoding_type_t type, chunk_t *encoding,
+bool pkcs1_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
va_list args)
{
switch (type)
{
- case KEY_ID_PUBKEY_INFO_SHA1:
+ case KEYID_PUBKEY_INFO_SHA1:
return build_info_sha1(encoding, args);
- case KEY_ID_PUBKEY_SHA1:
+ case KEYID_PUBKEY_SHA1:
return build_sha1(encoding, args);
- case KEY_PUB_ASN1_DER:
+ case PUBKEY_ASN1_DER:
return build_pub(encoding, args);
- case KEY_PUB_SPKI_ASN1_DER:
+ case PUBKEY_SPKI_ASN1_DER:
return build_pub_info(encoding, args);
- case KEY_PRIV_ASN1_DER:
+ case PRIVKEY_ASN1_DER:
return build_priv(encoding, args);
default:
return FALSE;
diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.h b/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.h
index 11d9f27f2..2eec736f1 100644
--- a/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.h
+++ b/src/libstrongswan/plugins/pkcs1/pkcs1_encoder.h
@@ -21,12 +21,12 @@
#ifndef PKCS1_ENCODER_H_
#define PKCS1_ENCODER_H_
-#include <credentials/keys/key_encoding.h>
+#include <credentials/cred_encoding.h>
/**
* Encoding function for PKCS#1/ASN.1 fingerprints/key formats.
*/
-bool pkcs1_encoder_encode(key_encoding_type_t type, chunk_t *encoding,
+bool pkcs1_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
va_list args);
#endif /** PKCS1_ENCODER_H_ @}*/
diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c
index cad279a9d..336d0bc02 100644
--- a/src/libstrongswan/plugins/plugin_loader.c
+++ b/src/libstrongswan/plugins/plugin_loader.c
@@ -118,8 +118,7 @@ static plugin_t* load_plugin(private_plugin_loader_t *this,
handle = dlopen(file, RTLD_LAZY);
if (handle == NULL)
{
- DBG1(DBG_LIB, "plugin '%s': failed to load '%s' - %s", name, file,
- dlerror());
+ DBG1(DBG_LIB, "plugin '%s' failed to load: %s", name, dlerror());
return NULL;
}
constructor = dlsym(handle, create);
diff --git a/src/libstrongswan/plugins/pubkey/Makefile.in b/src/libstrongswan/plugins/pubkey/Makefile.in
index 5fe3d58f1..4dc5985cd 100644
--- a/src/libstrongswan/plugins/pubkey/Makefile.in
+++ b/src/libstrongswan/plugins/pubkey/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/pubkey/pubkey_cert.c b/src/libstrongswan/plugins/pubkey/pubkey_cert.c
index f149f6379..c50189a8b 100644
--- a/src/libstrongswan/plugins/pubkey/pubkey_cert.c
+++ b/src/libstrongswan/plugins/pubkey/pubkey_cert.c
@@ -82,10 +82,10 @@ static id_match_t has_subject(private_pubkey_cert_t *this,
{
if (subject->get_type(subject) == ID_KEY_ID)
{
- key_encoding_type_t type;
+ cred_encoding_type_t type;
chunk_t fingerprint;
- for (type = 0; type < KEY_ENCODING_MAX; type++)
+ for (type = 0; type < CRED_ENCODING_MAX; type++)
{
if (this->key->get_fingerprint(this->key, type, &fingerprint) &&
chunk_equals(fingerprint, subject->get_encoding(subject)))
@@ -161,25 +161,12 @@ static bool get_validity(private_pubkey_cert_t *this, time_t *when,
}
/**
- * Implementation of certificate_t.is_newer.
- */
-static bool is_newer(certificate_t *this, certificate_t *that)
-{
- return FALSE;
-}
-
-/**
* Implementation of certificate_t.get_encoding.
*/
-static chunk_t get_encoding(private_pubkey_cert_t *this)
+static bool get_encoding(private_pubkey_cert_t *this, cred_encoding_type_t type,
+ chunk_t *encoding)
{
- chunk_t encoding;
-
- if (this->key->get_encoding(this->key, KEY_PUB_ASN1_DER, &encoding))
- {
- return encoding;
- }
- return chunk_empty;
+ return this->key->get_encoding(this->key, PUBKEY_ASN1_DER, encoding);
}
/**
@@ -221,8 +208,7 @@ static pubkey_cert_t *pubkey_cert_create(public_key_t *key)
this->public.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by;
this->public.interface.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
this->public.interface.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
- this->public.interface.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
- this->public.interface.get_encoding = (chunk_t (*)(certificate_t*))get_encoding;
+ this->public.interface.get_encoding = (bool (*)(certificate_t*,cred_encoding_type_t,chunk_t*))get_encoding;
this->public.interface.equals = (bool (*)(certificate_t*, certificate_t *other))equals;
this->public.interface.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
this->public.interface.destroy = (void (*)(certificate_t *this))destroy;
@@ -230,7 +216,7 @@ static pubkey_cert_t *pubkey_cert_create(public_key_t *key)
this->ref = 1;
this->key = key;
this->issuer = identification_create_from_encoding(ID_ANY, chunk_empty);
- if (key->get_fingerprint(key, KEY_ID_PUBKEY_INFO_SHA1, &fingerprint))
+ if (key->get_fingerprint(key, KEYID_PUBKEY_INFO_SHA1, &fingerprint))
{
this->subject = identification_create_from_encoding(ID_KEY_ID, fingerprint);
}
diff --git a/src/libstrongswan/plugins/random/Makefile.in b/src/libstrongswan/plugins/random/Makefile.in
index 27360aa8c..af929080d 100644
--- a/src/libstrongswan/plugins/random/Makefile.in
+++ b/src/libstrongswan/plugins/random/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/revocation/Makefile.am b/src/libstrongswan/plugins/revocation/Makefile.am
new file mode 100644
index 000000000..fb6d01926
--- /dev/null
+++ b/src/libstrongswan/plugins/revocation/Makefile.am
@@ -0,0 +1,16 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-revocation.la
+else
+plugin_LTLIBRARIES = libstrongswan-revocation.la
+endif
+
+libstrongswan_revocation_la_SOURCES = \
+ revocation_plugin.h revocation_plugin.c \
+ revocation_validator.h revocation_validator.c
+
+libstrongswan_revocation_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/revocation/Makefile.in b/src/libstrongswan/plugins/revocation/Makefile.in
new file mode 100644
index 000000000..871566e65
--- /dev/null
+++ b/src/libstrongswan/plugins/revocation/Makefile.in
@@ -0,0 +1,588 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = src/libstrongswan/plugins/revocation
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_revocation_la_LIBADD =
+am_libstrongswan_revocation_la_OBJECTS = revocation_plugin.lo \
+ revocation_validator.lo
+libstrongswan_revocation_la_OBJECTS = \
+ $(am_libstrongswan_revocation_la_OBJECTS)
+libstrongswan_revocation_la_LINK = $(LIBTOOL) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_revocation_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_revocation_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_revocation_la_rpath =
+DEFAULT_INCLUDES = -I.@am__isrc@
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(libstrongswan_revocation_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_revocation_la_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPERF = @GPERF@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PTHREADLIB = @PTHREADLIB@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYINCLUDE = @RUBYINCLUDE@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+default_pkcs11 = @default_pkcs11@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsecdir = @ipsecdir@
+ipsecgid = @ipsecgid@
+ipsecgroup = @ipsecgroup@
+ipsecuid = @ipsecuid@
+ipsecuser = @ipsecuser@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libhydra_plugins = @libhydra_plugins@
+libstrongswan_plugins = @libstrongswan_plugins@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+lt_ECHO = @lt_ECHO@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+piddir = @piddir@
+plugindir = @plugindir@
+pluto_plugins = @pluto_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+strongswan_conf = @strongswan_conf@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+INCLUDES = -I$(top_srcdir)/src/libstrongswan
+AM_CFLAGS = -rdynamic
+@MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-revocation.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-revocation.la
+libstrongswan_revocation_la_SOURCES = \
+ revocation_plugin.h revocation_plugin.c \
+ revocation_validator.h revocation_validator.c
+
+libstrongswan_revocation_la_LDFLAGS = -module -avoid-version
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libstrongswan/plugins/revocation/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libstrongswan/plugins/revocation/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
+ }
+
+uninstall-pluginLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
+ done
+
+clean-pluginLTLIBRARIES:
+ -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+ @list='$(plugin_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libstrongswan-revocation.la: $(libstrongswan_revocation_la_OBJECTS) $(libstrongswan_revocation_la_DEPENDENCIES)
+ $(libstrongswan_revocation_la_LINK) $(am_libstrongswan_revocation_la_rpath) $(libstrongswan_revocation_la_OBJECTS) $(libstrongswan_revocation_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revocation_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/revocation_validator.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+installdirs:
+ for dir in "$(DESTDIR)$(plugindir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pluginLTLIBRARIES mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-pluginLTLIBRARIES
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pluginLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pluginLTLIBRARIES install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pluginLTLIBRARIES
+
+
+# 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/plugins/revocation/revocation_plugin.c b/src/libstrongswan/plugins/revocation/revocation_plugin.c
new file mode 100644
index 000000000..d352a9583
--- /dev/null
+++ b/src/libstrongswan/plugins/revocation/revocation_plugin.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "revocation_plugin.h"
+
+#include <library.h>
+#include "revocation_validator.h"
+
+typedef struct private_revocation_plugin_t private_revocation_plugin_t;
+
+/**
+ * private data of revocation_plugin
+ */
+struct private_revocation_plugin_t {
+
+ /**
+ * public functions
+ */
+ revocation_plugin_t public;
+
+ /**
+ * Validator implementation instance.
+ */
+ revocation_validator_t *validator;
+};
+
+METHOD(plugin_t, destroy, void,
+ private_revocation_plugin_t *this)
+{
+ lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator);
+ this->validator->destroy(this->validator);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *revocation_plugin_create()
+{
+ private_revocation_plugin_t *this;
+
+ INIT(this,
+ .public.plugin.destroy = _destroy,
+ .validator = revocation_validator_create(),
+ );
+ lib->credmgr->add_validator(lib->credmgr, &this->validator->validator);
+
+ return &this->public.plugin;
+}
diff --git a/src/libstrongswan/plugins/revocation/revocation_plugin.h b/src/libstrongswan/plugins/revocation/revocation_plugin.h
new file mode 100644
index 000000000..fb886d53c
--- /dev/null
+++ b/src/libstrongswan/plugins/revocation/revocation_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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 revocation revocation
+ * @ingroup plugins
+ *
+ * @defgroup revocation_plugin revocation_plugin
+ * @{ @ingroup revocation
+ */
+
+#ifndef REVOCATION_PLUGIN_H_
+#define REVOCATION_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct revocation_plugin_t revocation_plugin_t;
+
+/**
+ * X509 certificate revocation support using CRL and OCSP.
+ */
+struct revocation_plugin_t {
+
+ /**
+ * Implements plugin_t. interface.
+ */
+ plugin_t plugin;
+};
+
+#endif /** REVOCATION_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/revocation/revocation_validator.c b/src/libstrongswan/plugins/revocation/revocation_validator.c
new file mode 100644
index 000000000..29d2bc128
--- /dev/null
+++ b/src/libstrongswan/plugins/revocation/revocation_validator.c
@@ -0,0 +1,587 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ * Copyright (C) 2009 Andreas Steffen
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "revocation_validator.h"
+
+#include <debug.h>
+#include <credentials/certificates/x509.h>
+#include <credentials/certificates/crl.h>
+#include <credentials/certificates/ocsp_request.h>
+#include <credentials/certificates/ocsp_response.h>
+#include <credentials/sets/ocsp_response_wrapper.h>
+#include <selectors/traffic_selector.h>
+
+typedef struct private_revocation_validator_t private_revocation_validator_t;
+
+/**
+ * Private data of an revocation_validator_t object.
+ */
+struct private_revocation_validator_t {
+
+ /**
+ * Public revocation_validator_t interface.
+ */
+ revocation_validator_t public;
+};
+
+/**
+ * Do an OCSP request
+ */
+static certificate_t *fetch_ocsp(char *url, certificate_t *subject,
+ certificate_t *issuer)
+{
+ certificate_t *request, *response;
+ chunk_t send, receive;
+
+ /* TODO: requestor name, signature */
+ request = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
+ BUILD_CA_CERT, issuer,
+ BUILD_CERT, subject, BUILD_END);
+ if (!request)
+ {
+ DBG1(DBG_CFG, "generating ocsp request failed");
+ return NULL;
+ }
+
+ if (!request->get_encoding(request, CERT_ASN1_DER, &send))
+ {
+ DBG1(DBG_CFG, "encoding ocsp request failed");
+ request->destroy(request);
+ return NULL;
+ }
+ request->destroy(request);
+
+ DBG1(DBG_CFG, " requesting ocsp status from '%s' ...", url);
+ if (lib->fetcher->fetch(lib->fetcher, url, &receive,
+ FETCH_REQUEST_DATA, send,
+ FETCH_REQUEST_TYPE, "application/ocsp-request",
+ FETCH_END) != SUCCESS)
+ {
+ DBG1(DBG_CFG, "ocsp request to %s failed", url);
+ chunk_free(&send);
+ return NULL;
+ }
+ chunk_free(&send);
+
+ response = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,
+ BUILD_BLOB_ASN1_DER, receive, BUILD_END);
+ chunk_free(&receive);
+ if (!response)
+ {
+ DBG1(DBG_CFG, "parsing ocsp response failed");
+ return NULL;
+ }
+ return response;
+}
+
+/**
+ * check the signature of an OCSP response
+ */
+static bool verify_ocsp(ocsp_response_t *response)
+{
+ certificate_t *issuer, *subject;
+ identification_t *responder;
+ ocsp_response_wrapper_t *wrapper;
+ enumerator_t *enumerator;
+ bool verified = FALSE;
+
+ wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
+ lib->credmgr->add_local_set(lib->credmgr, &wrapper->set);
+
+ subject = &response->certificate;
+ responder = subject->get_issuer(subject);
+ enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
+ KEY_ANY, responder, FALSE);
+ while (enumerator->enumerate(enumerator, &issuer, NULL))
+ {
+ if (lib->credmgr->issued_by(lib->credmgr, subject, issuer))
+ {
+ DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"",
+ issuer->get_subject(issuer));
+ verified = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ lib->credmgr->remove_local_set(lib->credmgr, &wrapper->set);
+ wrapper->destroy(wrapper);
+ return verified;
+}
+
+/**
+ * Get the better of two OCSP responses, and check for usable OCSP info
+ */
+static certificate_t *get_better_ocsp(certificate_t *cand, certificate_t *best,
+ x509_t *subject, x509_t *issuer, cert_validation_t *valid, bool cache)
+{
+ ocsp_response_t *response;
+ time_t revocation, this_update, next_update, valid_until;
+ crl_reason_t reason;
+ bool revoked = FALSE;
+
+ response = (ocsp_response_t*)cand;
+
+ /* check ocsp signature */
+ if (!verify_ocsp(response))
+ {
+ DBG1(DBG_CFG, "ocsp response verification failed");
+ cand->destroy(cand);
+ return best;
+ }
+ /* check if response contains our certificate */
+ switch (response->get_status(response, subject, issuer, &revocation, &reason,
+ &this_update, &next_update))
+ {
+ case VALIDATION_REVOKED:
+ /* subject has been revoked by a valid OCSP response */
+ DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
+ &revocation, TRUE, crl_reason_names, reason);
+ revoked = TRUE;
+ break;
+ case VALIDATION_GOOD:
+ /* results in either good or stale */
+ break;
+ default:
+ case VALIDATION_FAILED:
+ /* candidate unusable, does not contain our cert */
+ DBG1(DBG_CFG, " ocsp response contains no status on our certificate");
+ cand->destroy(cand);
+ return best;
+ }
+
+ /* select the better of the two responses */
+ if (best == NULL || certificate_is_newer(cand, best))
+ {
+ DESTROY_IF(best);
+ best = cand;
+ if (best->get_validity(best, NULL, NULL, &valid_until))
+ {
+ DBG1(DBG_CFG, " ocsp response is valid: until %T",
+ &valid_until, FALSE);
+ *valid = VALIDATION_GOOD;
+ if (cache)
+ { /* cache non-stale only, stale certs get refetched */
+ lib->credmgr->cache_cert(lib->credmgr, best);
+ }
+ }
+ else
+ {
+ DBG1(DBG_CFG, " ocsp response is stale: since %T",
+ &valid_until, FALSE);
+ *valid = VALIDATION_STALE;
+ }
+ }
+ else
+ {
+ *valid = VALIDATION_STALE;
+ cand->destroy(cand);
+ }
+ if (revoked)
+ { /* revoked always counts, even if stale */
+ *valid = VALIDATION_REVOKED;
+ }
+ return best;
+}
+
+/**
+ * validate a x509 certificate using OCSP
+ */
+static cert_validation_t check_ocsp(x509_t *subject, x509_t *issuer,
+ auth_cfg_t *auth)
+{
+ enumerator_t *enumerator;
+ cert_validation_t valid = VALIDATION_SKIPPED;
+ certificate_t *best = NULL, *current;
+ identification_t *keyid = NULL;
+ public_key_t *public;
+ chunk_t chunk;
+ char *uri = NULL;
+
+ /** lookup cache for valid OCSP responses */
+ enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+ CERT_X509_OCSP_RESPONSE, KEY_ANY, NULL, FALSE);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ current->get_ref(current);
+ best = get_better_ocsp(current, best, subject, issuer, &valid, FALSE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ DBG1(DBG_CFG, " using cached ocsp response");
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* derive the authorityKeyIdentifier from the issuer's public key */
+ current = &issuer->interface;
+ public = current->get_public_key(current);
+ if (public && public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
+ {
+ keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
+ }
+ /** fetch from configured OCSP responder URLs */
+ if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
+ {
+ enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr,
+ CERT_X509_OCSP_RESPONSE, keyid);
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ current = fetch_ocsp(uri, &subject->interface, &issuer->interface);
+ if (current)
+ {
+ best = get_better_ocsp(current, best, subject, issuer,
+ &valid, TRUE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ DESTROY_IF(public);
+ DESTROY_IF(keyid);
+
+ /* fallback to URL fetching from subject certificate's URIs */
+ if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
+ {
+ enumerator = subject->create_ocsp_uri_enumerator(subject);
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ current = fetch_ocsp(uri, &subject->interface, &issuer->interface);
+ if (current)
+ {
+ best = get_better_ocsp(current, best, subject, issuer,
+ &valid, TRUE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ /* an uri was found, but no result. switch validation state to failed */
+ if (valid == VALIDATION_SKIPPED && uri)
+ {
+ valid = VALIDATION_FAILED;
+ }
+ if (auth)
+ {
+ auth->add(auth, AUTH_RULE_OCSP_VALIDATION, valid);
+ if (valid == VALIDATION_GOOD)
+ { /* successful OCSP check fulfills also CRL constraint */
+ auth->add(auth, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
+ }
+ }
+ DESTROY_IF(best);
+ return valid;
+}
+
+/**
+ * fetch a CRL from an URL
+ */
+static certificate_t* fetch_crl(char *url)
+{
+ certificate_t *crl;
+ chunk_t chunk;
+
+ DBG1(DBG_CFG, " fetching crl from '%s' ...", url);
+ if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS)
+ {
+ DBG1(DBG_CFG, "crl fetching failed");
+ return NULL;
+ }
+ crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
+ BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
+ chunk_free(&chunk);
+ if (!crl)
+ {
+ DBG1(DBG_CFG, "crl fetched successfully but parsing failed");
+ return NULL;
+ }
+ return crl;
+}
+
+/**
+ * check the signature of an CRL
+ */
+static bool verify_crl(certificate_t *crl)
+{
+ certificate_t *issuer;
+ enumerator_t *enumerator;
+ bool verified = FALSE;
+
+ enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
+ KEY_ANY, crl->get_issuer(crl), FALSE);
+ while (enumerator->enumerate(enumerator, &issuer, NULL))
+ {
+ if (lib->credmgr->issued_by(lib->credmgr, crl, issuer))
+ {
+ DBG1(DBG_CFG, " crl correctly signed by \"%Y\"",
+ issuer->get_subject(issuer));
+ verified = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return verified;
+}
+
+/**
+ * Get the better of two CRLs, and check for usable CRL info
+ */
+static certificate_t *get_better_crl(certificate_t *cand, certificate_t *best,
+ x509_t *subject, x509_t *issuer, cert_validation_t *valid, bool cache)
+{
+ enumerator_t *enumerator;
+ time_t revocation, valid_until;
+ crl_reason_t reason;
+ chunk_t serial;
+ crl_t *crl;
+
+ /* check CRL signature */
+ if (!verify_crl(cand))
+ {
+ DBG1(DBG_CFG, "crl response verification failed");
+ cand->destroy(cand);
+ return best;
+ }
+
+ crl = (crl_t*)cand;
+ enumerator = crl->create_enumerator(crl);
+ while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
+ {
+ if (chunk_equals(serial, subject->get_serial(subject)))
+ {
+ DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
+ &revocation, TRUE, crl_reason_names, reason);
+ *valid = VALIDATION_REVOKED;
+ enumerator->destroy(enumerator);
+ DESTROY_IF(best);
+ return cand;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* select the better of the two CRLs */
+ if (best == NULL || crl_is_newer(crl, (crl_t*)best))
+ {
+ DESTROY_IF(best);
+ best = cand;
+ if (best->get_validity(best, NULL, NULL, &valid_until))
+ {
+ DBG1(DBG_CFG, " crl is valid: until %T", &valid_until, FALSE);
+ *valid = VALIDATION_GOOD;
+ if (cache)
+ { /* we cache non-stale crls only, as a stale crls are refetched */
+ lib->credmgr->cache_cert(lib->credmgr, best);
+ }
+ }
+ else
+ {
+ DBG1(DBG_CFG, " crl is stale: since %T", &valid_until, FALSE);
+ *valid = VALIDATION_STALE;
+ }
+ }
+ else
+ {
+ *valid = VALIDATION_STALE;
+ cand->destroy(cand);
+ }
+ return best;
+}
+
+/**
+ * validate a x509 certificate using CRL
+ */
+static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
+ auth_cfg_t *auth)
+{
+ cert_validation_t valid = VALIDATION_SKIPPED;
+ identification_t *keyid = NULL;
+ certificate_t *best = NULL;
+ certificate_t *current;
+ public_key_t *public;
+ enumerator_t *enumerator;
+ chunk_t chunk;
+ char *uri = NULL;
+
+ /* derive the authorityKeyIdentifier from the issuer's public key */
+ current = &issuer->interface;
+ public = current->get_public_key(current);
+ if (public && public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
+ {
+ keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
+
+ /* find a cached crl by authorityKeyIdentifier */
+ enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
+ CERT_X509_CRL, KEY_ANY, keyid, FALSE);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ current->get_ref(current);
+ best = get_better_crl(current, best, subject, issuer,
+ &valid, FALSE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ DBG1(DBG_CFG, " using cached crl");
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* fallback to fetching crls from credential sets cdps */
+ if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
+ {
+ enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr,
+ CERT_X509_CRL, keyid);
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ current = fetch_crl(uri);
+ if (current)
+ {
+ best = get_better_crl(current, best, subject, issuer,
+ &valid, TRUE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ keyid->destroy(keyid);
+ }
+ DESTROY_IF(public);
+
+ /* fallback to fetching crls from cdps from subject's certificate */
+ if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
+ {
+ enumerator = subject->create_crl_uri_enumerator(subject);
+
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ current = fetch_crl(uri);
+ if (current)
+ {
+ best = get_better_crl(current, best, subject, issuer,
+ &valid, TRUE);
+ if (best && valid != VALIDATION_STALE)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+
+ /* an uri was found, but no result. switch validation state to failed */
+ if (valid == VALIDATION_SKIPPED && uri)
+ {
+ valid = VALIDATION_FAILED;
+ }
+ if (auth)
+ {
+ if (valid == VALIDATION_SKIPPED)
+ { /* if we skipped CRL validation, we use the result of OCSP for
+ * constraint checking */
+ auth->add(auth, AUTH_RULE_CRL_VALIDATION,
+ auth->get(auth, AUTH_RULE_OCSP_VALIDATION));
+ }
+ else
+ {
+ auth->add(auth, AUTH_RULE_CRL_VALIDATION, valid);
+ }
+ }
+ DESTROY_IF(best);
+ return valid;
+}
+
+METHOD(cert_validator_t, validate, bool,
+ private_revocation_validator_t *this, certificate_t *subject,
+ certificate_t *issuer, bool online, int pathlen, auth_cfg_t *auth)
+{
+ if (subject->get_type(subject) == CERT_X509 &&
+ issuer->get_type(issuer) == CERT_X509 &&
+ online)
+ {
+ DBG1(DBG_CFG, "checking certificate status of \"%Y\"",
+ subject->get_subject(subject));
+ switch (check_ocsp((x509_t*)subject, (x509_t*)issuer, auth))
+ {
+ case VALIDATION_GOOD:
+ DBG1(DBG_CFG, "certificate status is good");
+ return TRUE;
+ case VALIDATION_REVOKED:
+ /* has already been logged */
+ return FALSE;
+ case VALIDATION_SKIPPED:
+ DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
+ break;
+ case VALIDATION_STALE:
+ DBG1(DBG_CFG, "ocsp information stale, fallback to crl");
+ break;
+ case VALIDATION_FAILED:
+ DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
+ break;
+ }
+ switch (check_crl((x509_t*)subject, (x509_t*)issuer, auth))
+ {
+ case VALIDATION_GOOD:
+ DBG1(DBG_CFG, "certificate status is good");
+ return TRUE;
+ case VALIDATION_REVOKED:
+ /* has already been logged */
+ return FALSE;
+ case VALIDATION_FAILED:
+ case VALIDATION_SKIPPED:
+ DBG1(DBG_CFG, "certificate status is not available");
+ break;
+ case VALIDATION_STALE:
+ DBG1(DBG_CFG, "certificate status is unknown, crl is stale");
+ break;
+ }
+ }
+ return TRUE;
+}
+
+METHOD(revocation_validator_t, destroy, void,
+ private_revocation_validator_t *this)
+{
+ free(this);
+}
+
+/**
+ * See header
+ */
+revocation_validator_t *revocation_validator_create()
+{
+ private_revocation_validator_t *this;
+
+ INIT(this,
+ .public = {
+ .validator.validate = _validate,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/plugins/revocation/revocation_validator.h b/src/libstrongswan/plugins/revocation/revocation_validator.h
new file mode 100644
index 000000000..82cbde26b
--- /dev/null
+++ b/src/libstrongswan/plugins/revocation/revocation_validator.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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 revocation_validator revocation_validator
+ * @{ @ingroup revocation
+ */
+
+#ifndef REVOCATION_VALIDATOR_H_
+#define REVOCATION_VALIDATOR_H_
+
+#include <credentials/cert_validator.h>
+
+typedef struct revocation_validator_t revocation_validator_t;
+
+/**
+ * Certificate validator doing CRL/OCSP checking of X509 certificates.
+ */
+struct revocation_validator_t {
+
+ /**
+ * Implements cert_validator_t interface.
+ */
+ cert_validator_t validator;
+
+ /**
+ * Destroy a revocation_validator_t.
+ */
+ void (*destroy)(revocation_validator_t *this);
+};
+
+/**
+ * Create a revocation_validator instance.
+ */
+revocation_validator_t *revocation_validator_create();
+
+#endif /** REVOCATION_VALIDATOR_H_ @}*/
diff --git a/src/libstrongswan/plugins/sha1/Makefile.in b/src/libstrongswan/plugins/sha1/Makefile.in
index dacb5be4b..703764e5e 100644
--- a/src/libstrongswan/plugins/sha1/Makefile.in
+++ b/src/libstrongswan/plugins/sha1/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/sha2/Makefile.in b/src/libstrongswan/plugins/sha2/Makefile.in
index 6db4374c8..5e490f2e5 100644
--- a/src/libstrongswan/plugins/sha2/Makefile.in
+++ b/src/libstrongswan/plugins/sha2/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/sqlite/Makefile.in b/src/libstrongswan/plugins/sqlite/Makefile.in
index cb466ad03..6d81d0d81 100644
--- a/src/libstrongswan/plugins/sqlite/Makefile.in
+++ b/src/libstrongswan/plugins/sqlite/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.in b/src/libstrongswan/plugins/test_vectors/Makefile.in
index dbe62c056..20a6db81e 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.in
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/x509/Makefile.in b/src/libstrongswan/plugins/x509/Makefile.in
index 2bee453cd..f40427f3f 100644
--- a/src/libstrongswan/plugins/x509/Makefile.in
+++ b/src/libstrongswan/plugins/x509/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c
index 95e72789e..ba0357cc4 100644
--- a/src/libstrongswan/plugins/x509/x509_ac.c
+++ b/src/libstrongswan/plugins/x509/x509_ac.c
@@ -568,7 +568,7 @@ static chunk_t build_authorityKeyIdentifier(private_x509_ac_t *this)
public = this->signerCert->get_public_key(this->signerCert);
if (public)
{
- if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &keyIdentifier))
+ if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyIdentifier))
{
this->authKeyIdentifier = chunk_clone(keyIdentifier);
}
@@ -749,7 +749,7 @@ static bool issued_by(private_x509_ac_t *this, certificate_t *issuer)
{
chunk_t fingerprint;
- if (!key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &fingerprint) ||
+ if (!key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fingerprint) ||
!chunk_equals(fingerprint, this->authKeyIdentifier))
{
return FALSE;
@@ -813,30 +813,18 @@ static bool get_validity(private_x509_ac_t *this, time_t *when,
}
/**
- * Implementation of certificate_t.is_newer.
- */
-static bool is_newer(private_x509_ac_t *this, ac_t *that)
-{
- certificate_t *this_cert = &this->public.interface.certificate;
- certificate_t *that_cert = &that->certificate;
- time_t this_update, that_update, now = time(NULL);
- bool new;
-
- this_cert->get_validity(this_cert, &now, &this_update, NULL);
- that_cert->get_validity(that_cert, &now, &that_update, NULL);
- new = this_update > that_update;
- DBG1(DBG_LIB, " attr cert from %T is %s - existing attr cert from %T %s",
- &this_update, FALSE, new ? "newer":"not newer",
- &that_update, FALSE, new ? "replaced":"retained");
- return new;
-}
-
-/**
* Implementation of certificate_t.get_encoding.
*/
-static chunk_t get_encoding(private_x509_ac_t *this)
+static bool get_encoding(private_x509_ac_t *this, cred_encoding_type_t type,
+ chunk_t *encoding)
{
- return chunk_clone(this->encoding);
+ if (type == CERT_ASN1_DER)
+ {
+ *encoding = chunk_clone(this->encoding);
+ return TRUE;
+ }
+ return lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_X509_AC_ASN1_DER, this->encoding, CRED_PART_END);
}
/**
@@ -855,7 +843,10 @@ static bool equals(private_x509_ac_t *this, certificate_t *other)
{ /* skip allocation if we have the same implementation */
return chunk_equals(this->encoding, ((private_x509_ac_t*)other)->encoding);
}
- encoding = other->get_encoding(other);
+ if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
+ {
+ return FALSE;
+ }
equal = chunk_equals(this->encoding, encoding);
free(encoding.ptr);
return equal;
@@ -904,8 +895,7 @@ static private_x509_ac_t *create_empty(void)
this->public.interface.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by;
this->public.interface.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
this->public.interface.certificate.get_validity = (bool(*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
- this->public.interface.certificate.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
- this->public.interface.certificate.get_encoding = (chunk_t(*)(certificate_t*))get_encoding;
+ this->public.interface.certificate.get_encoding = (bool(*)(certificate_t*,cred_encoding_type_t,chunk_t*))get_encoding;
this->public.interface.certificate.equals = (bool(*)(certificate_t*, certificate_t *other))equals;
this->public.interface.certificate.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
this->public.interface.certificate.destroy = (void (*)(certificate_t *this))destroy;
diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c
index bdbaa8d4a..92b576aa5 100644
--- a/src/libstrongswan/plugins/x509/x509_cert.c
+++ b/src/libstrongswan/plugins/x509/x509_cert.c
@@ -366,7 +366,17 @@ static identification_t *parse_generalName(chunk_t blob, int level0)
id_type = ID_DER_ASN1_DN;
break;
case GN_OBJ_IP_ADDRESS:
- id_type = ID_IPV4_ADDR;
+ switch (object.len)
+ {
+ case 4:
+ id_type = ID_IPV4_ADDR;
+ break;
+ case 16:
+ id_type = ID_IPV6_ADDR;
+ break;
+ default:
+ break;
+ }
break;
case GN_OBJ_OTHER_NAME:
if (!parse_otherName(object, parser->get_level(parser)+1))
@@ -1209,28 +1219,18 @@ static bool get_validity(private_x509_cert_t *this, time_t *when,
}
/**
- * Implementation of certificate_t.is_newer.
- */
-static bool is_newer(certificate_t *this, certificate_t *that)
-{
- time_t this_update, that_update, now = time(NULL);
- bool new;
-
- this->get_validity(this, &now, &this_update, NULL);
- that->get_validity(that, &now, &that_update, NULL);
- new = this_update > that_update;
- DBG1(DBG_LIB, " certificate from %T is %s - existing certificate "
- "from %T %s", &this_update, FALSE, new ? "newer":"not newer",
- &that_update, FALSE, new ? "replaced":"retained");
- return new;
-}
-
-/**
* Implementation of certificate_t.get_encoding.
*/
-static chunk_t get_encoding(private_x509_cert_t *this)
+static bool get_encoding(private_x509_cert_t *this, cred_encoding_type_t type,
+ chunk_t *encoding)
{
- return chunk_clone(this->encoding);
+ if (type == CERT_ASN1_DER)
+ {
+ *encoding = chunk_clone(this->encoding);
+ return TRUE;
+ }
+ return lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_X509_ASN1_DER, this->encoding, CRED_PART_END);
}
/**
@@ -1253,7 +1253,10 @@ static bool equals(private_x509_cert_t *this, certificate_t *other)
{ /* skip allocation if we have the same implementation */
return chunk_equals(this->encoding, ((private_x509_cert_t*)other)->encoding);
}
- encoding = other->get_encoding(other);
+ if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
+ {
+ return FALSE;
+ }
equal = chunk_equals(this->encoding, encoding);
free(encoding.ptr);
return equal;
@@ -1281,7 +1284,7 @@ static chunk_t get_subjectKeyIdentifier(private_x509_cert_t *this)
chunk_t fingerprint;
if (this->public_key->get_fingerprint(this->public_key,
- KEY_ID_PUBKEY_SHA1, &fingerprint))
+ KEYID_PUBKEY_SHA1, &fingerprint))
{
return fingerprint;
}
@@ -1383,8 +1386,7 @@ static private_x509_cert_t* create_empty(void)
this->public.interface.interface.issued_by = (bool (*) (certificate_t*, certificate_t*))issued_by;
this->public.interface.interface.get_public_key = (public_key_t* (*) (certificate_t*))get_public_key;
this->public.interface.interface.get_validity = (bool (*) (certificate_t*, time_t*, time_t*, time_t*))get_validity;
- this->public.interface.interface.is_newer = (bool (*) (certificate_t*,certificate_t*))is_newer;
- this->public.interface.interface.get_encoding = (chunk_t (*) (certificate_t*))get_encoding;
+ this->public.interface.interface.get_encoding = (bool (*) (certificate_t*,cred_encoding_type_t,chunk_t*))get_encoding;
this->public.interface.interface.equals = (bool (*)(certificate_t*, certificate_t*))equals;
this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t*))get_ref;
this->public.interface.interface.destroy = (void (*)(certificate_t*))destroy;
@@ -1536,7 +1538,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
scheme = signature_scheme_from_oid(cert->algorithm);
if (!cert->public_key->get_encoding(cert->public_key,
- KEY_PUB_SPKI_ASN1_DER, &key_info))
+ PUBKEY_SPKI_ASN1_DER, &key_info))
{
return FALSE;
}
@@ -1650,7 +1652,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
chunk_t keyid;
if (cert->public_key->get_fingerprint(cert->public_key,
- KEY_ID_PUBKEY_SHA1, &keyid))
+ KEYID_PUBKEY_SHA1, &keyid))
{
subjectKeyIdentifier = asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_build_known_oid(OID_SUBJECT_KEY_ID),
@@ -1664,7 +1666,7 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert,
{
chunk_t keyid;
- if (sign_key->get_fingerprint(sign_key, KEY_ID_PUBKEY_SHA1, &keyid))
+ if (sign_key->get_fingerprint(sign_key, KEYID_PUBKEY_SHA1, &keyid))
{
authKeyIdentifier = asn1_wrap(ASN1_SEQUENCE, "mm",
asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c
index c755d7f63..4bd0470d3 100644
--- a/src/libstrongswan/plugins/x509/x509_crl.c
+++ b/src/libstrongswan/plugins/x509/x509_crl.c
@@ -26,6 +26,7 @@ typedef struct revoked_t revoked_t;
#include <asn1/asn1.h>
#include <asn1/asn1_parser.h>
#include <credentials/certificates/x509.h>
+#include <credentials/keys/private_key.h>
#include <utils/linked_list.h>
/**
@@ -119,6 +120,11 @@ struct private_x509_crl_t {
chunk_t signature;
/**
+ * has this CRL been generated
+ */
+ bool generated;
+
+ /**
* reference counter
*/
refcount_t ref;
@@ -236,7 +242,7 @@ static bool parse(private_x509_crl_t *this)
break;
case CRL_OBJ_REVOCATION_DATE:
revoked = malloc_thing(revoked_t);
- revoked->serial = userCertificate;
+ revoked->serial = chunk_clone(userCertificate);
revoked->date = asn1_parse_time(object, level);
revoked->reason = CRL_REASON_UNSPECIFIED;
this->revoked->insert_last(this->revoked, (void *)revoked);
@@ -267,7 +273,6 @@ static bool parse(private_x509_crl_t *this)
}
else if (extn_oid == OID_AUTHORITY_KEY_ID)
{
-
this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object,
level, &this->authKeySerialNumber);
}
@@ -327,52 +332,40 @@ static bool filter(void *data, revoked_t **revoked, chunk_t *serial, void *p2,
return TRUE;
}
-/**
- * Implementation of crl_t.get_serial.
- */
-static chunk_t get_serial(private_x509_crl_t *this)
+METHOD(crl_t, get_serial, chunk_t,
+ private_x509_crl_t *this)
{
return this->crlNumber;
}
-/**
- * Implementation of crl_t.get_authKeyIdentifier.
- */
-static chunk_t get_authKeyIdentifier(private_x509_crl_t *this)
+METHOD(crl_t, get_authKeyIdentifier, chunk_t,
+ private_x509_crl_t *this)
{
return this->authKeyIdentifier;
}
-/**
- * Implementation of crl_t.create_enumerator.
- */
-static enumerator_t* create_enumerator(private_x509_crl_t *this)
+METHOD(crl_t, create_enumerator, enumerator_t*,
+ private_x509_crl_t *this)
{
return enumerator_create_filter(
this->revoked->create_enumerator(this->revoked),
(void*)filter, NULL, NULL);
}
-/**
- * Implementation of certificate_t.get_type
- */
-static certificate_type_t get_type(private_x509_crl_t *this)
+METHOD(certificate_t, get_type, certificate_type_t,
+ private_x509_crl_t *this)
{
return CERT_X509_CRL;
}
-/**
- * Implementation of certificate_t.get_issuer and get_subject
- */
-static identification_t* get_issuer(private_x509_crl_t *this)
+METHOD(certificate_t, get_issuer, identification_t*,
+ private_x509_crl_t *this)
{
return this->issuer;
}
-/**
- * Implementation of certificate_t.has_subject and has_issuer.
- */
-static id_match_t has_issuer(private_x509_crl_t *this, identification_t *issuer)
+METHOD(certificate_t, has_issuer, id_match_t,
+ private_x509_crl_t *this, identification_t *issuer)
{
if (issuer->get_type(issuer) == ID_KEY_ID && this->authKeyIdentifier.ptr &&
chunk_equals(this->authKeyIdentifier, issuer->get_encoding(issuer)))
@@ -382,10 +375,8 @@ static id_match_t has_issuer(private_x509_crl_t *this, identification_t *issuer)
return this->issuer->matches(this->issuer, issuer);
}
-/**
- * Implementation of certificate_t.issued_by
- */
-static bool issued_by(private_x509_crl_t *this, certificate_t *issuer)
+METHOD(certificate_t, issued_by, bool,
+ private_x509_crl_t *this, certificate_t *issuer)
{
public_key_t *key;
signature_scheme_t scheme;
@@ -410,7 +401,7 @@ static bool issued_by(private_x509_crl_t *this, certificate_t *issuer)
{
chunk_t fingerprint;
- if (!key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &fingerprint) ||
+ if (!key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fingerprint) ||
!chunk_equals(fingerprint, this->authKeyIdentifier))
{
return FALSE;
@@ -436,28 +427,22 @@ static bool issued_by(private_x509_crl_t *this, certificate_t *issuer)
return valid;
}
-/**
- * Implementation of certificate_t.get_public_key
- */
-static public_key_t* get_public_key(private_x509_crl_t *this)
+METHOD(certificate_t, get_public_key, public_key_t*,
+ private_x509_crl_t *this)
{
return NULL;
}
-/**
- * Implementation of certificate_t.asdf
- */
-static private_x509_crl_t* get_ref(private_x509_crl_t *this)
+METHOD(certificate_t, get_ref, certificate_t*,
+ private_x509_crl_t *this)
{
ref_get(&this->ref);
- return this;
+ return &this->public.crl.certificate;
}
-/**
- * Implementation of certificate_t.get_validity.
- */
-static bool get_validity(private_x509_crl_t *this, time_t *when,
- time_t *not_before, time_t *not_after)
+METHOD(certificate_t, get_validity, bool,
+ private_x509_crl_t *this, time_t *when,
+ time_t *not_before, time_t *not_after)
{
time_t t = when ? *when : time(NULL);
@@ -472,51 +457,20 @@ static bool get_validity(private_x509_crl_t *this, time_t *when,
return (t <= this->nextUpdate);
}
-/**
- * Implementation of certificate_t.is_newer.
- */
-static bool is_newer(private_x509_crl_t *this, crl_t *that)
+METHOD(certificate_t, get_encoding, bool,
+ private_x509_crl_t *this, cred_encoding_type_t type, chunk_t *encoding)
{
- chunk_t that_crlNumber = that->get_serial(that);
- bool new;
-
- /* compare crlNumbers if available - otherwise use thisUpdate */
- if (this->crlNumber.ptr != NULL && that_crlNumber.ptr != NULL)
+ if (type == CERT_ASN1_DER)
{
- new = chunk_compare(this->crlNumber, that_crlNumber) > 0;
- DBG1(DBG_LIB, " crl #%#B is %s - existing crl #%#B %s",
- &this->crlNumber, new ? "newer":"not newer",
- &that_crlNumber, new ? "replaced":"retained");
- }
- else
- {
- certificate_t *this_cert = &this->public.crl.certificate;
- certificate_t *that_cert = &that->certificate;
-
- time_t this_update, that_update, now = time(NULL);
-
- this_cert->get_validity(this_cert, &now, &this_update, NULL);
- that_cert->get_validity(that_cert, &now, &that_update, NULL);
- new = this_update > that_update;
- DBG1(DBG_LIB, " crl from %T is %s - existing crl from %T %s",
- &this_update, FALSE, new ? "newer":"not newer",
- &that_update, FALSE, new ? "replaced":"retained");
+ *encoding = chunk_clone(this->encoding);
+ return TRUE;
}
- return new;
-}
-
-/**
- * Implementation of certificate_t.get_encoding.
- */
-static chunk_t get_encoding(private_x509_crl_t *this)
-{
- return chunk_clone(this->encoding);
+ return lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_X509_CRL_ASN1_DER, this->encoding, CRED_PART_END);
}
-/**
- * Implementation of certificate_t.equals.
- */
-static bool equals(private_x509_crl_t *this, certificate_t *other)
+METHOD(certificate_t, equals, bool,
+ private_x509_crl_t *this, certificate_t *other)
{
chunk_t encoding;
bool equal;
@@ -529,23 +483,39 @@ static bool equals(private_x509_crl_t *this, certificate_t *other)
{ /* skip allocation if we have the same implementation */
return chunk_equals(this->encoding, ((private_x509_crl_t*)other)->encoding);
}
- encoding = other->get_encoding(other);
+ if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
+ {
+ return FALSE;
+ }
equal = chunk_equals(this->encoding, encoding);
free(encoding.ptr);
return equal;
}
/**
- * Implementation of certificate_t.destroy
+ * Destroy a revoked_t entry
*/
-static void destroy(private_x509_crl_t *this)
+static void revoked_destroy(revoked_t *revoked)
+{
+ free(revoked->serial.ptr);
+ free(revoked);
+}
+
+METHOD(certificate_t, destroy, void,
+ private_x509_crl_t *this)
{
if (ref_put(&this->ref))
{
- this->revoked->destroy_function(this->revoked, free);
+ this->revoked->destroy_function(this->revoked, (void*)revoked_destroy);
DESTROY_IF(this->issuer);
free(this->authKeyIdentifier.ptr);
free(this->encoding.ptr);
+ if (this->generated)
+ {
+ free(this->crlNumber.ptr);
+ free(this->signature.ptr);
+ free(this->tbsCertList.ptr);
+ }
free(this);
}
}
@@ -555,34 +525,33 @@ static void destroy(private_x509_crl_t *this)
*/
static private_x509_crl_t* create_empty(void)
{
- private_x509_crl_t *this = malloc_thing(private_x509_crl_t);
-
- this->public.crl.get_serial = (chunk_t (*)(crl_t*))get_serial;
- this->public.crl.get_authKeyIdentifier = (chunk_t (*)(crl_t*))get_authKeyIdentifier;
- this->public.crl.create_enumerator = (enumerator_t* (*)(crl_t*))create_enumerator;
- this->public.crl.certificate.get_type = (certificate_type_t (*)(certificate_t *this))get_type;
- this->public.crl.certificate.get_subject = (identification_t* (*)(certificate_t *this))get_issuer;
- this->public.crl.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
- this->public.crl.certificate.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_issuer;
- this->public.crl.certificate.has_issuer = (id_match_t (*)(certificate_t*, identification_t *issuer))has_issuer;
- this->public.crl.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by;
- this->public.crl.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
- this->public.crl.certificate.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
- this->public.crl.certificate.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
- this->public.crl.certificate.get_encoding = (chunk_t (*)(certificate_t*))get_encoding;
- this->public.crl.certificate.equals = (bool (*)(certificate_t*, certificate_t *other))equals;
- this->public.crl.certificate.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
- this->public.crl.certificate.destroy = (void (*)(certificate_t *this))destroy;
-
- this->encoding = chunk_empty;
- this->tbsCertList = chunk_empty;
- this->issuer = NULL;
- this->crlNumber = chunk_empty;
- this->revoked = linked_list_create();
- this->authKeyIdentifier = chunk_empty;
- this->authKeySerialNumber = chunk_empty;
- this->ref = 1;
-
+ private_x509_crl_t *this;
+
+ INIT(this,
+ .public = {
+ .crl = {
+ .certificate = {
+ .get_type = _get_type,
+ .get_subject = _get_issuer,
+ .get_issuer = _get_issuer,
+ .has_subject = _has_issuer,
+ .has_issuer = _has_issuer,
+ .issued_by = _issued_by,
+ .get_public_key = _get_public_key,
+ .get_validity = _get_validity,
+ .get_encoding = _get_encoding,
+ .equals = _equals,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_serial = _get_serial,
+ .get_authKeyIdentifier = _get_authKeyIdentifier,
+ .create_enumerator = _create_enumerator,
+ },
+ },
+ .revoked = linked_list_create(),
+ .ref = 1,
+ );
return this;
}
@@ -621,3 +590,166 @@ x509_crl_t *x509_crl_load(certificate_type_t type, va_list args)
return NULL;
};
+/**
+ * Read certificate status from enumerator, copy to crl
+ */
+static void read_revoked(private_x509_crl_t *crl, enumerator_t *enumerator)
+{
+ revoked_t *revoked;
+ chunk_t serial;
+ time_t date;
+ crl_reason_t reason;
+
+ while (enumerator->enumerate(enumerator, &serial, &date, &reason))
+ {
+ INIT(revoked,
+ .serial = chunk_clone(serial),
+ .date = date,
+ .reason = reason,
+ );
+ crl->revoked->insert_last(crl->revoked, revoked);
+ }
+}
+
+/**
+ * Generate CRL encoding, sign CRL
+ */
+static bool generate(private_x509_crl_t *this, certificate_t *cert,
+ private_key_t *key, hash_algorithm_t digest_alg)
+{
+ chunk_t extensions = chunk_empty, certList = chunk_empty, serial;
+ enumerator_t *enumerator;
+ crl_reason_t reason;
+ time_t date;
+ x509_t *x509;
+
+ x509 = (x509_t*)cert;
+
+ this->issuer = cert->get_issuer(cert);
+ this->issuer = this->issuer->clone(this->issuer);
+
+ this->authKeyIdentifier = chunk_clone(x509->get_subjectKeyIdentifier(x509));
+
+ /* select signature scheme */
+ this->algorithm = hasher_signature_algorithm_to_oid(digest_alg,
+ key->get_type(key));
+ if (this->algorithm == OID_UNKNOWN)
+ {
+ return FALSE;
+ }
+
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &serial, &date, &reason))
+ {
+ chunk_t revoked, entry_ext = chunk_empty;
+
+ if (reason != CRL_REASON_UNSPECIFIED)
+ {
+ entry_ext = asn1_wrap(ASN1_SEQUENCE, "m",
+ asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(OID_CRL_REASON_CODE),
+ asn1_wrap(ASN1_OCTET_STRING, "m",
+ asn1_wrap(ASN1_ENUMERATED, "c",
+ chunk_from_chars(reason)))));
+ }
+ revoked = asn1_wrap(ASN1_SEQUENCE, "mmm",
+ asn1_integer("c", serial),
+ asn1_from_time(&date, ASN1_UTCTIME),
+ entry_ext);
+ certList = chunk_cat("mm", certList, revoked);
+ }
+ enumerator->destroy(enumerator);
+
+ extensions = asn1_wrap(ASN1_CONTEXT_C_0, "m",
+ asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
+ asn1_wrap(ASN1_OCTET_STRING, "m",
+ asn1_wrap(ASN1_SEQUENCE, "m",
+ asn1_wrap(ASN1_CONTEXT_S_0, "c",
+ this->authKeyIdentifier)))),
+ asn1_wrap(ASN1_SEQUENCE, "mm",
+ asn1_build_known_oid(OID_CRL_NUMBER),
+ asn1_wrap(ASN1_OCTET_STRING, "m",
+ asn1_integer("c", this->crlNumber))
+ )
+ ));
+
+ this->tbsCertList = asn1_wrap(ASN1_SEQUENCE, "cmcmmmm",
+ ASN1_INTEGER_1,
+ asn1_algorithmIdentifier(this->algorithm),
+ this->issuer->get_encoding(this->issuer),
+ asn1_from_time(&this->thisUpdate, ASN1_UTCTIME),
+ asn1_from_time(&this->nextUpdate, ASN1_UTCTIME),
+ asn1_wrap(ASN1_SEQUENCE, "m", certList),
+ extensions);
+
+ if (!key->sign(key, signature_scheme_from_oid(this->algorithm),
+ this->tbsCertList, &this->signature))
+ {
+ return FALSE;
+ }
+ this->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm",
+ this->tbsCertList,
+ asn1_algorithmIdentifier(this->algorithm),
+ asn1_bitstring("c", this->signature));
+ return TRUE;
+}
+
+/**
+ * See header.
+ */
+x509_crl_t *x509_crl_gen(certificate_type_t type, va_list args)
+{
+ hash_algorithm_t digest_alg = HASH_SHA1;
+ private_x509_crl_t *crl;
+ certificate_t *cert = NULL;
+ private_key_t *key = NULL;
+
+ crl = create_empty();
+ crl->generated = TRUE;
+ while (TRUE)
+ {
+ builder_part_t part = va_arg(args, builder_part_t);
+
+ switch (part)
+ {
+ case BUILD_SIGNING_KEY:
+ key = va_arg(args, private_key_t*);
+ continue;
+ case BUILD_SIGNING_CERT:
+ cert = va_arg(args, certificate_t*);
+ continue;
+ case BUILD_NOT_BEFORE_TIME:
+ crl->thisUpdate = va_arg(args, time_t);
+ continue;
+ case BUILD_NOT_AFTER_TIME:
+ crl->nextUpdate = va_arg(args, time_t);
+ continue;
+ case BUILD_SERIAL:
+ crl->crlNumber = va_arg(args, chunk_t);
+ crl->crlNumber = chunk_clone(crl->crlNumber);
+ continue;
+ case BUILD_DIGEST_ALG:
+ digest_alg = va_arg(args, int);
+ continue;
+ case BUILD_REVOKED_ENUMERATOR:
+ read_revoked(crl, va_arg(args, enumerator_t*));
+ continue;
+ case BUILD_END:
+ break;
+ default:
+ destroy(crl);
+ return NULL;
+ }
+ break;
+ }
+
+ if (key && cert && cert->get_type(cert) == CERT_X509 &&
+ generate(crl, cert, key, digest_alg))
+ {
+ return &crl->public;
+ }
+ destroy(crl);
+ return NULL;
+}
diff --git a/src/libstrongswan/plugins/x509/x509_crl.h b/src/libstrongswan/plugins/x509/x509_crl.h
index 890650162..e8fe74e81 100644
--- a/src/libstrongswan/plugins/x509/x509_crl.h
+++ b/src/libstrongswan/plugins/x509/x509_crl.h
@@ -46,4 +46,13 @@ struct x509_crl_t {
*/
x509_crl_t *x509_crl_load(certificate_type_t type, va_list args);
+/**
+ * Generate a X.509 CRL.
+ *
+ * @param type certificate type, CERT_X509_CRL only
+ * @param args builder_part_t argument list
+ * @return X.509 CRL, NULL on failure
+ */
+x509_crl_t *x509_crl_gen(certificate_type_t type, va_list args);
+
#endif /** X509_CRL_H_ @}*/
diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.c b/src/libstrongswan/plugins/x509/x509_ocsp_request.c
index c835d5dc8..ea02cbab5 100644
--- a/src/libstrongswan/plugins/x509/x509_ocsp_request.c
+++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.c
@@ -153,7 +153,7 @@ static chunk_t build_requestList(private_x509_ocsp_request_t *this)
hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
if (hasher)
{
- if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1,
+ if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1,
&issuerKeyHash))
{
enumerator_t *enumerator;
@@ -250,7 +250,7 @@ static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this,
{
int oid;
signature_scheme_t scheme;
- chunk_t certs, signature;
+ chunk_t certs, signature, encoding;
switch (this->key->get_type(this->key))
{
@@ -274,11 +274,11 @@ static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this,
DBG1(DBG_LIB, "creating OCSP signature failed, skipped");
return chunk_empty;
}
- if (this->cert)
+ if (this->cert &&
+ this->cert->get_encoding(this->cert, CERT_ASN1_DER, &encoding))
{
certs = asn1_wrap(ASN1_CONTEXT_C_0, "m",
- asn1_wrap(ASN1_SEQUENCE, "m",
- this->cert->get_encoding(this->cert)));
+ asn1_wrap(ASN1_SEQUENCE, "m", encoding));
}
return asn1_wrap(ASN1_CONTEXT_C_0, "m",
asn1_wrap(ASN1_SEQUENCE, "cmm",
@@ -413,9 +413,16 @@ static bool get_validity(private_x509_ocsp_request_t *this, time_t *when,
/**
* Implementation of certificate_t.get_encoding.
*/
-static chunk_t get_encoding(private_x509_ocsp_request_t *this)
+static bool get_encoding(private_x509_ocsp_request_t *this,
+ cred_encoding_type_t type, chunk_t *encoding)
{
- return chunk_clone(this->encoding);
+ if (type == CERT_ASN1_DER)
+ {
+ *encoding = chunk_clone(this->encoding);
+ return TRUE;
+ }
+ return lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_X509_OCSP_REQ_ASN1_DER, this->encoding, CRED_PART_END);
}
/**
@@ -438,7 +445,10 @@ static bool equals(private_x509_ocsp_request_t *this, certificate_t *other)
{ /* skip allocation if we have the same implementation */
return chunk_equals(this->encoding, ((private_x509_ocsp_request_t*)other)->encoding);
}
- encoding = other->get_encoding(other);
+ if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
+ {
+ return FALSE;
+ }
equal = chunk_equals(this->encoding, encoding);
free(encoding.ptr);
return equal;
@@ -486,7 +496,7 @@ static private_x509_ocsp_request_t *create_empty()
this->public.interface.interface.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by;
this->public.interface.interface.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
this->public.interface.interface.get_validity = (bool(*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
- this->public.interface.interface.get_encoding = (chunk_t(*)(certificate_t*))get_encoding;
+ this->public.interface.interface.get_encoding = (bool(*)(certificate_t*,cred_encoding_type_t,chunk_t*))get_encoding;
this->public.interface.interface.equals = (bool(*)(certificate_t*, certificate_t *other))equals;
this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
this->public.interface.interface.destroy = (void (*)(certificate_t *this))destroy;
diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
index c70d461df..829f47f81 100644
--- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c
+++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c
@@ -167,7 +167,7 @@ static cert_validation_t get_status(private_x509_ocsp_response_t *this,
{
hasher_t *hasher;
identification_t *id;
- key_encoding_type_t type;
+ cred_encoding_type_t type;
chunk_t hash, fingerprint;
/* check serial first, is cheaper */
@@ -188,7 +188,7 @@ static cert_validation_t get_status(private_x509_ocsp_response_t *this,
switch (response->hashAlgorithm)
{
case OID_SHA1:
- type = KEY_ID_PUBKEY_SHA1;
+ type = KEYID_PUBKEY_SHA1;
break;
default:
public->destroy(public);
@@ -698,7 +698,7 @@ static bool issued_by(private_x509_ocsp_response_t *this, certificate_t *issuer)
key = issuer->get_public_key(issuer);
if (!key ||
- !key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &fingerprint) ||
+ !key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fingerprint) ||
!chunk_equals(fingerprint,
this->responderId->get_encoding(this->responderId)))
{
@@ -764,28 +764,18 @@ static bool get_validity(private_x509_ocsp_response_t *this, time_t *when,
}
/**
- * Implementation of certificate_t.is_newer.
- */
-static bool is_newer(certificate_t *this, certificate_t *that)
-{
- time_t this_update, that_update, now = time(NULL);
- bool new;
-
- this->get_validity(this, &now, &this_update, NULL);
- that->get_validity(that, &now, &that_update, NULL);
- new = this_update > that_update;
- DBG1(DBG_LIB, " ocsp response from %T is %s - existing ocsp response "
- "from %T %s", &this_update, FALSE, new ? "newer" : "not newer",
- &that_update, FALSE, new ? "replaced" : "retained");
- return new;
-}
-
-/**
* Implementation of certificate_t.get_encoding.
*/
-static chunk_t get_encoding(private_x509_ocsp_response_t *this)
+static bool get_encoding(private_x509_ocsp_response_t *this,
+ cred_encoding_type_t type, chunk_t *encoding)
{
- return chunk_clone(this->encoding);
+ if (type == CERT_ASN1_DER)
+ {
+ *encoding = chunk_clone(this->encoding);
+ return TRUE;
+ }
+ return lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_X509_OCSP_RES_ASN1_DER, this->encoding, CRED_PART_END);
}
/**
@@ -808,7 +798,10 @@ static bool equals(private_x509_ocsp_response_t *this, certificate_t *other)
{ /* skip allocation if we have the same implementation */
return chunk_equals(this->encoding, ((private_x509_ocsp_response_t*)other)->encoding);
}
- encoding = other->get_encoding(other);
+ if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
+ {
+ return FALSE;
+ }
equal = chunk_equals(this->encoding, encoding);
free(encoding.ptr);
return equal;
@@ -855,8 +848,7 @@ static x509_ocsp_response_t *load(chunk_t blob)
this->public.interface.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by;
this->public.interface.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
this->public.interface.certificate.get_validity = (bool(*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
- this->public.interface.certificate.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
- this->public.interface.certificate.get_encoding = (chunk_t(*)(certificate_t*))get_encoding;
+ this->public.interface.certificate.get_encoding = (bool(*)(certificate_t*,cred_encoding_type_t,chunk_t*))get_encoding;
this->public.interface.certificate.equals = (bool(*)(certificate_t*, certificate_t *other))equals;
this->public.interface.certificate.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
this->public.interface.certificate.destroy = (void (*)(certificate_t *this))destroy;
diff --git a/src/libstrongswan/plugins/x509/x509_pkcs10.c b/src/libstrongswan/plugins/x509/x509_pkcs10.c
index 1009ec931..bfb0ca621 100644
--- a/src/libstrongswan/plugins/x509/x509_pkcs10.c
+++ b/src/libstrongswan/plugins/x509/x509_pkcs10.c
@@ -189,19 +189,18 @@ static bool get_validity(private_x509_pkcs10_t *this, time_t *when,
}
/**
- * Implementation of certificate_t.is_newer.
- */
-static bool is_newer(certificate_t *this, certificate_t *that)
-{
- return FALSE;
-}
-
-/**
* Implementation of certificate_t.get_encoding.
*/
-static chunk_t get_encoding(private_x509_pkcs10_t *this)
+static bool get_encoding(private_x509_pkcs10_t *this, cred_encoding_type_t type,
+ chunk_t *encoding)
{
- return chunk_clone(this->encoding);
+ if (type == CERT_ASN1_DER)
+ {
+ *encoding = chunk_clone(this->encoding);
+ return TRUE;
+ }
+ return lib->encoding->encode(lib->encoding, type, NULL, encoding,
+ CRED_PART_PKCS10_ASN1_DER, this->encoding, CRED_PART_END);
}
/**
@@ -224,7 +223,10 @@ static bool equals(private_x509_pkcs10_t *this, certificate_t *other)
{ /* skip allocation if we have the same implementation */
return chunk_equals(this->encoding, ((private_x509_pkcs10_t*)other)->encoding);
}
- encoding = other->get_encoding(other);
+ if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
+ {
+ return FALSE;
+ }
equal = chunk_equals(this->encoding, encoding);
free(encoding.ptr);
return equal;
@@ -357,7 +359,7 @@ static bool parse_challengePassword(private_x509_pkcs10_t *this, chunk_t blob, i
*/
static const asn1Object_t certificationRequestObjects[] = {
{ 0, "certificationRequest", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
- { 1, "certificationRequestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
+ { 1, "certificationRequestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
{ 2, "version", ASN1_INTEGER, ASN1_BODY }, /* 2 */
{ 2, "subject", ASN1_SEQUENCE, ASN1_OBJ }, /* 3 */
{ 2, "subjectPublicKeyInfo", ASN1_SEQUENCE, ASN1_RAW }, /* 4 */
@@ -369,7 +371,7 @@ static const asn1Object_t certificationRequestObjects[] = {
{ 4, "end loop", ASN1_EOC, ASN1_END }, /* 10 */
{ 2, "end loop", ASN1_EOC, ASN1_END }, /* 11 */
{ 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 12 */
- { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 13 */
+ { 1, "signature", ASN1_BIT_STRING, ASN1_BODY }, /* 13 */
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
};
#define PKCS10_CERT_REQUEST_INFO 1
@@ -512,8 +514,7 @@ static private_x509_pkcs10_t* create_empty(void)
this->public.interface.interface.issued_by = (bool (*) (certificate_t*, certificate_t*))issued_by;
this->public.interface.interface.get_public_key = (public_key_t* (*) (certificate_t*))get_public_key;
this->public.interface.interface.get_validity = (bool (*) (certificate_t*, time_t*, time_t*, time_t*))get_validity;
- this->public.interface.interface.is_newer = (bool (*) (certificate_t*,certificate_t*))is_newer;
- this->public.interface.interface.get_encoding = (chunk_t (*) (certificate_t*))get_encoding;
+ this->public.interface.interface.get_encoding = (bool (*) (certificate_t*,cred_encoding_type_t,chunk_t*))get_encoding;
this->public.interface.interface.equals = (bool (*)(certificate_t*, certificate_t*))equals;
this->public.interface.interface.get_ref = (certificate_t* (*)(certificate_t*))get_ref;
this->public.interface.interface.destroy = (void (*)(certificate_t*))destroy;
@@ -559,7 +560,7 @@ static bool generate(private_x509_pkcs10_t *cert, private_key_t *sign_key,
scheme = signature_scheme_from_oid(cert->algorithm);
if (!cert->public_key->get_encoding(cert->public_key,
- KEY_PUB_SPKI_ASN1_DER, &key_info))
+ PUBKEY_SPKI_ASN1_DER, &key_info))
{
return FALSE;
}
diff --git a/src/libstrongswan/plugins/x509/x509_plugin.c b/src/libstrongswan/plugins/x509/x509_plugin.c
index e71c55efc..8391781e2 100644
--- a/src/libstrongswan/plugins/x509/x509_plugin.c
+++ b/src/libstrongswan/plugins/x509/x509_plugin.c
@@ -52,6 +52,8 @@ static void destroy(private_x509_plugin_t *this)
lib->creds->remove_builder(lib->creds,
(builder_function_t)x509_crl_load);
lib->creds->remove_builder(lib->creds,
+ (builder_function_t)x509_crl_gen);
+ lib->creds->remove_builder(lib->creds,
(builder_function_t)x509_ocsp_request_gen);
lib->creds->remove_builder(lib->creds,
(builder_function_t)x509_ocsp_response_load);
@@ -81,6 +83,8 @@ plugin_t *x509_plugin_create()
(builder_function_t)x509_ac_load);
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
(builder_function_t)x509_crl_load);
+ lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
+ (builder_function_t)x509_crl_gen);
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
(builder_function_t)x509_ocsp_request_gen);
lib->creds->add_builder(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,
diff --git a/src/libstrongswan/plugins/xcbc/Makefile.in b/src/libstrongswan/plugins/xcbc/Makefile.in
index c49e2b76a..69bba8d6f 100644
--- a/src/libstrongswan/plugins/xcbc/Makefile.in
+++ b/src/libstrongswan/plugins/xcbc/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11 from Makefile.am.
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
diff --git a/src/libstrongswan/threading/lock_profiler.h b/src/libstrongswan/threading/lock_profiler.h
index b64453ba1..1ae496455 100644
--- a/src/libstrongswan/threading/lock_profiler.h
+++ b/src/libstrongswan/threading/lock_profiler.h
@@ -63,7 +63,7 @@ static inline void profiler_cleanup(lock_profile_t *profile)
{
fprintf(stderr, "%d.%03ds / %d times in lock created at:",
profile->waited.tv_sec, profile->waited.tv_usec, profile->locked);
- profile->backtrace->log(profile->backtrace, stderr);
+ profile->backtrace->log(profile->backtrace, stderr, TRUE);
}
profile->backtrace->destroy(profile->backtrace);
}
diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c
index 5bba8ec21..a67245194 100644
--- a/src/libstrongswan/utils/backtrace.c
+++ b/src/libstrongswan/utils/backtrace.c
@@ -53,7 +53,7 @@ struct private_backtrace_t {
/**
* Implementation of backtrace_t.log
*/
-static void log_(private_backtrace_t *this, FILE *file)
+static void log_(private_backtrace_t *this, FILE *file, bool detailed)
{
#ifdef HAVE_BACKTRACE
size_t i;
@@ -78,7 +78,6 @@ static void log_(private_backtrace_t *this, FILE *file)
{
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",
@@ -90,28 +89,33 @@ static void log_(private_backtrace_t *this, FILE *file)
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)
+ if (detailed)
{
- while (TRUE)
+ fprintf(file, " -> \e[32m");
+ snprintf(cmd, sizeof(cmd), "addr2line -e %s %p",
+ info.dli_fname, ptr);
+ output = popen(cmd, "r");
+ if (output)
{
- c = getc(output);
- if (c == '\n' || c == EOF)
+ while (TRUE)
{
- break;
+ c = getc(output);
+ if (c == '\n' || c == EOF)
+ {
+ break;
+ }
+ fputc(c, file);
}
- fputc(c, file);
+ pclose(output);
}
- pclose(output);
- }
- else
- {
-#endif /* HAVE_DLADDR */
- fprintf(file, " %s\n", strings[i]);
-#ifdef HAVE_DLADDR
+ else
+ {
+ #endif /* HAVE_DLADDR */
+ fprintf(file, " %s\n", strings[i]);
+ #ifdef HAVE_DLADDR
+ }
+ fprintf(file, "\n\e[0m");
}
- fprintf(file, "\n\e[0m");
}
else
{
@@ -174,7 +178,7 @@ backtrace_t *backtrace_create(int skip)
memcpy(this->frames, frames + skip, frame_count * sizeof(void*));
this->frame_count = frame_count;
- this->public.log = (void(*)(backtrace_t*,FILE*))log_;
+ this->public.log = (void(*)(backtrace_t*,FILE*,bool))log_;
this->public.contains_function = (bool(*)(backtrace_t*, char *function))contains_function;
this->public.destroy = (void(*)(backtrace_t*))destroy;
diff --git a/src/libstrongswan/utils/backtrace.h b/src/libstrongswan/utils/backtrace.h
index c4d4284d1..c6b0ec78f 100644
--- a/src/libstrongswan/utils/backtrace.h
+++ b/src/libstrongswan/utils/backtrace.h
@@ -34,8 +34,11 @@ struct backtrace_t {
/**
* Log the backtrace to a FILE stream.
+ *
+ * @param file FILE to log backtrace to
+ * @param detailed TRUE to resolve line/file using addr2line (slow)
*/
- void (*log)(backtrace_t *this, FILE *file);
+ void (*log)(backtrace_t *this, FILE *file, bool detailed);
/**
* Check if the backtrace contains a frame in a specific function.
diff --git a/src/libstrongswan/utils/hashtable.c b/src/libstrongswan/utils/hashtable.c
index 02c225833..dde57dc65 100644
--- a/src/libstrongswan/utils/hashtable.c
+++ b/src/libstrongswan/utils/hashtable.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2010 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -47,11 +47,13 @@ struct pair_t {
*/
pair_t *pair_create(void *key, void *value, u_int hash)
{
- pair_t *this = malloc_thing(pair_t);
+ pair_t *this;
- this->key = key;
- this->value = value;
- this->hash = hash;
+ INIT(this,
+ .key = key,
+ .value = value,
+ .hash = hash,
+ );
return this;
}
@@ -127,6 +129,11 @@ struct private_enumerator_t {
u_int row;
/**
+ * current pair
+ */
+ pair_t *pair;
+
+ /**
* enumerator for the current row
*/
enumerator_t *current;
@@ -219,10 +226,8 @@ static void rehash(private_hashtable_t *this)
free(old_table);
}
-/**
- * Implementation of hashtable_t.put
- */
-static void *put(private_hashtable_t *this, void *key, void *value)
+METHOD(hashtable_t, put, void*,
+ private_hashtable_t *this, void *key, void *value)
{
void *old_value = NULL;
linked_list_t *list;
@@ -265,10 +270,8 @@ static void *put(private_hashtable_t *this, void *key, void *value)
return old_value;
}
-/**
- * Implementation of hashtable_t.get
- */
-static void *get(private_hashtable_t *this, void *key)
+METHOD(hashtable_t, get, void*,
+ private_hashtable_t *this, void *key)
{
void *value = NULL;
linked_list_t *list;
@@ -286,10 +289,8 @@ static void *get(private_hashtable_t *this, void *key)
return value;
}
-/**
- * Implementation of hashtable_t.remove
- */
-static void *remove_(private_hashtable_t *this, void *key)
+METHOD(hashtable_t, remove_, void*,
+ private_hashtable_t *this, void *key)
{
void *value = NULL;
linked_list_t *list;
@@ -317,34 +318,44 @@ static void *remove_(private_hashtable_t *this, void *key)
return value;
}
-/**
- * Implementation of hashtable_t.get_count
- */
-static u_int get_count(private_hashtable_t *this)
+METHOD(hashtable_t, remove_at, void,
+ private_hashtable_t *this, private_enumerator_t *enumerator)
+{
+ if (enumerator->table == this && enumerator->current)
+ {
+ linked_list_t *list;
+ list = this->table[enumerator->row];
+ if (list)
+ {
+ list->remove_at(list, enumerator->current);
+ free(enumerator->pair);
+ this->count--;
+ }
+ }
+}
+
+METHOD(hashtable_t, get_count, u_int,
+ private_hashtable_t *this)
{
return this->count;
}
-/**
- * Implementation of private_enumerator_t.enumerator.enumerate.
- */
-static bool enumerate(private_enumerator_t *this, void **key, void **value)
+METHOD(enumerator_t, enumerate, bool,
+ private_enumerator_t *this, void **key, void **value)
{
while (this->row < this->table->capacity)
{
if (this->current)
{
- pair_t *pair;
-
- if (this->current->enumerate(this->current, &pair))
+ if (this->current->enumerate(this->current, &this->pair))
{
if (key)
{
- *key = pair->key;
+ *key = this->pair->key;
}
if (value)
{
- *value = pair->value;
+ *value = this->pair->value;
}
return TRUE;
}
@@ -354,7 +365,6 @@ static bool enumerate(private_enumerator_t *this, void **key, void **value)
else
{
linked_list_t *list;
-
list = this->table->table[this->row];
if (list)
{
@@ -367,10 +377,8 @@ static bool enumerate(private_enumerator_t *this, void **key, void **value)
return FALSE;
}
-/**
- * Implementation of private_enumerator_t.enumerator.destroy.
- */
-static void enumerator_destroy(private_enumerator_t *this)
+METHOD(enumerator_t, enumerator_destroy, void,
+ private_enumerator_t *this)
{
if (this->current)
{
@@ -379,26 +387,24 @@ static void enumerator_destroy(private_enumerator_t *this)
free(this);
}
-/**
- * Implementation of hashtable_t.create_enumerator.
- */
-static enumerator_t* create_enumerator(private_hashtable_t *this)
+METHOD(hashtable_t, create_enumerator, enumerator_t*,
+ private_hashtable_t *this)
{
- private_enumerator_t *enumerator = malloc_thing(private_enumerator_t);
+ private_enumerator_t *enumerator;
- enumerator->enumerator.enumerate = (void*)enumerate;
- enumerator->enumerator.destroy = (void*)enumerator_destroy;
- enumerator->table = this;
- enumerator->row = 0;
- enumerator->current = NULL;
+ INIT(enumerator,
+ .enumerator = {
+ .enumerate = (void*)_enumerate,
+ .destroy = (void*)_enumerator_destroy,
+ },
+ .table = this,
+ );
return &enumerator->enumerator;
}
-/**
- * Implementation of hashtable_t.destroy
- */
-static void destroy(private_hashtable_t *this)
+METHOD(hashtable_t, destroy, void,
+ private_hashtable_t *this)
{
linked_list_t *list;
u_int row;
@@ -421,22 +427,21 @@ static void destroy(private_hashtable_t *this)
hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals,
u_int capacity)
{
- private_hashtable_t *this = malloc_thing(private_hashtable_t);
-
- this->public.put = (void*(*)(hashtable_t*,void*,void*))put;
- this->public.get = (void*(*)(hashtable_t*,void*))get;
- this->public.remove = (void*(*)(hashtable_t*,void*))remove_;
- this->public.get_count = (u_int(*)(hashtable_t*))get_count;
- this->public.create_enumerator = (enumerator_t*(*)(hashtable_t*))create_enumerator;
- this->public.destroy = (void(*)(hashtable_t*))destroy;
-
- this->count = 0;
- this->capacity = 0;
- this->mask = 0;
- this->load_factor = 0;
- this->table = NULL;
- this->hash = hash;
- this->equals = equals;
+ private_hashtable_t *this;
+
+ INIT(this,
+ .public = {
+ .put = _put,
+ .get = _get,
+ .remove = _remove_,
+ .remove_at = (void*)_remove_at,
+ .get_count = _get_count,
+ .create_enumerator = _create_enumerator,
+ .destroy = _destroy,
+ },
+ .hash = hash,
+ .equals = equals,
+ );
init_hashtable(this, capacity);
diff --git a/src/libstrongswan/utils/hashtable.h b/src/libstrongswan/utils/hashtable.h
index 142ea6329..27aca9b68 100644
--- a/src/libstrongswan/utils/hashtable.h
+++ b/src/libstrongswan/utils/hashtable.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2010 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -87,9 +87,17 @@ struct hashtable_t {
void *(*remove) (hashtable_t *this, void *key);
/**
+ * Removes the key and value pair from the hash table at which the given
+ * enumerator currently points.
+ *
+ * @param enumerator enumerator, from create_enumerator
+ */
+ void (*remove_at) (hashtable_t *this, enumerator_t *enumerator);
+
+ /**
* Gets the number of items in the hash table.
*
- * @return number of items
+ * @return number of items
*/
u_int (*get_count) (hashtable_t *this);
@@ -106,7 +114,7 @@ struct hashtable_t {
* @param hash hash function
* @param equals equals function
* @param capacity initial capacity
- * @return hashtable_t object.
+ * @return hashtable_t object.
*/
hashtable_t *hashtable_create(hashtable_hash_t hash, hashtable_equals_t equals,
u_int capacity);
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index 6a3c3936c..3caeb8f0e 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -50,8 +50,7 @@ ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID,
"ID_DER_ASN1_GN",
"ID_KEY_ID");
ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_MYID, ID_KEY_ID,
- "ID_DER_ASN1_GN_URI"
- "ID_IETF_ATTR_STRING"
+ "ID_DER_ASN1_GN_URI",
"ID_MYID");
ENUM_END(id_type_names, ID_MYID);
@@ -297,18 +296,30 @@ static void dntoa(chunk_t dn, char *buf, size_t len)
{
written = snprintf(buf, len,"%s=", oid_names[oid].name);
}
+ if (written < 0 || written >= len)
+ {
+ break;
+ }
buf += written;
len -= written;
chunk_printable(data, &printable, '?');
written = snprintf(buf, len, "%.*s", printable.len, printable.ptr);
chunk_free(&printable);
+ if (written < 0 || written >= len)
+ {
+ break;
+ }
buf += written;
len -= written;
if (data.ptr + data.len != dn.ptr + dn.len)
{
written = snprintf(buf, len, ", ");
+ if (written < 0 || written >= len)
+ {
+ break;
+ }
buf += written;
len -= written;
}
@@ -761,7 +772,6 @@ int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
case ID_FQDN:
case ID_RFC822_ADDR:
case ID_DER_ASN1_GN_URI:
- case ID_IETF_ATTR_STRING:
chunk_printable(this->encoded, &proper, '?');
snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr);
chunk_free(&proper);
diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h
index fe5c7d0fd..c463b0274 100644
--- a/src/libstrongswan/utils/identification.h
+++ b/src/libstrongswan/utils/identification.h
@@ -131,11 +131,6 @@ enum id_type_t {
ID_DER_ASN1_GN_URI = 201,
/**
- * IETF Attribute Syntax String (RFC 3281)
- */
- ID_IETF_ATTR_STRING = 202,
-
- /**
* Private ID used by the pluto daemon for opportunistic encryption
*/
ID_MYID = 203,
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index 2f8a7187c..0673878a5 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -207,6 +207,7 @@ char *whitelist[] = {
"ENGINE_load_builtin_engines",
"OPENSSL_config",
"ecdsa_check",
+ "ERR_put_error",
/* libgcrypt */
"gcry_control",
"gcry_check_version",
@@ -233,39 +234,45 @@ static bool is_whitelisted(backtrace_t *backtrace)
/**
* Report leaks at library destruction
*/
-void report_leaks()
+static void report(private_leak_detective_t *this, bool detailed)
{
- memory_header_t *hdr;
- int leaks = 0, whitelisted = 0;
-
- for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
+ if (lib->leak_detective)
{
- if (is_whitelisted(hdr->backtrace))
+ memory_header_t *hdr;
+ int leaks = 0, whitelisted = 0;
+
+ for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
{
- whitelisted++;
+ if (is_whitelisted(hdr->backtrace))
+ {
+ whitelisted++;
+ }
+ else
+ {
+ fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1);
+ /* skip the first frame, contains leak detective logic */
+ hdr->backtrace->log(hdr->backtrace, stderr, detailed);
+ leaks++;
+ }
}
- else
+ switch (leaks)
{
- fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1);
- /* skip the first frame, contains leak detective logic */
- hdr->backtrace->log(hdr->backtrace, stderr);
- leaks++;
+ case 0:
+ fprintf(stderr, "No leaks detected");
+ break;
+ case 1:
+ fprintf(stderr, "One leak detected");
+ break;
+ default:
+ fprintf(stderr, "%d leaks detected", leaks);
+ break;
}
+ fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted);
}
-
- switch (leaks)
+ else
{
- case 0:
- fprintf(stderr, "No leaks detected");
- break;
- case 1:
- fprintf(stderr, "One leak detected");
- break;
- default:
- fprintf(stderr, "%d leaks detected", leaks);
- break;
+ fprintf(stderr, "Leak detective disabled\n");
}
- fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted);
}
/**
@@ -395,7 +402,7 @@ void free_hook(void *ptr, const void *caller)
fprintf(stderr, "freeing invalid memory (%p)", ptr);
}
backtrace = backtrace_create(3);
- backtrace->log(backtrace, stderr);
+ backtrace->log(backtrace, stderr, TRUE);
backtrace->destroy(backtrace);
}
else
@@ -454,7 +461,7 @@ void *realloc_hook(void *old, size_t bytes, const void *caller)
"header magic 0x%x, tail magic 0x%x:\n",
old, hdr->magic, tail->magic);
backtrace = backtrace_create(3);
- backtrace->log(backtrace, stderr);
+ backtrace->log(backtrace, stderr, TRUE);
backtrace->destroy(backtrace);
}
/* clear tail magic, allocate, set tail magic */
@@ -487,7 +494,6 @@ static void destroy(private_leak_detective_t *this)
if (installed)
{
uninstall_hooks();
- report_leaks();
}
free(this);
}
@@ -499,6 +505,7 @@ leak_detective_t *leak_detective_create()
{
private_leak_detective_t *this = malloc_thing(private_leak_detective_t);
+ this->public.report = (void(*)(leak_detective_t*,bool))report;
this->public.destroy = (void(*)(leak_detective_t*))destroy;
if (getenv("LEAK_DETECTIVE_DISABLE") == NULL)
diff --git a/src/libstrongswan/utils/leak_detective.h b/src/libstrongswan/utils/leak_detective.h
index 181f8f3db..fa45a6076 100644
--- a/src/libstrongswan/utils/leak_detective.h
+++ b/src/libstrongswan/utils/leak_detective.h
@@ -23,6 +23,8 @@
typedef struct leak_detective_t leak_detective_t;
+#include <library.h>
+
/**
* Leak detective finds leaks and bad frees using malloc hooks.
*
@@ -34,6 +36,13 @@ typedef struct leak_detective_t leak_detective_t;
struct leak_detective_t {
/**
+ * Report leaks to stderr.
+ *
+ * @param detailed TRUE to resolve line/filename of leak (slow)
+ */
+ void (*report)(leak_detective_t *this, bool detailed);
+
+ /**
* Destroy a leak_detective instance.
*/
void (*destroy)(leak_detective_t *this);