diff options
Diffstat (limited to 'src/libstrongswan')
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, ¤t_type, ¤t_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, ¤t)) + { + /* 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, ¤t, &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, ¬_before, ¬_after)) + { + DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)", + ¬_before, FALSE, ¬_after, FALSE); + return FALSE; + } + if (!issuer->get_validity(issuer, NULL, ¬_before, ¬_after)) + { + DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)", + ¬_before, FALSE, ¬_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, ¤t)) + { + 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, ¤t) && 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, ¤t) && 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, ¤t)) + { + 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**)¤t)) + { + 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, ¤t)) + { + 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, ¤t)) + { + 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, ¤t)) + { + 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, ¤t)) + { + 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); |