From 08ee5250bd9c43fda5f24d10b791ca2c4c17fcee Mon Sep 17 00:00:00 2001 From: Rene Mayrhofer Date: Sun, 3 Jun 2007 17:36:35 +0000 Subject: [svn-upgrade] Integrating new upstream version, strongswan (4.1.3) --- src/libstrongswan/Makefile.am | 1 + src/libstrongswan/Makefile.in | 26 +- src/libstrongswan/asn1/asn1.c | 40 ++ src/libstrongswan/asn1/asn1.h | 2 + src/libstrongswan/asn1/oid.c | 283 ++++++------- src/libstrongswan/asn1/oid.h | 112 +++--- src/libstrongswan/asn1/oid.txt | 7 +- src/libstrongswan/chunk.c | 1 + src/libstrongswan/credential_store.h | 47 ++- src/libstrongswan/crypto/ac.c | 665 +++++++++++++++++++++++++++++++ src/libstrongswan/crypto/ac.h | 81 ++++ src/libstrongswan/crypto/ca.c | 179 +++++---- src/libstrongswan/crypto/ca.h | 38 +- src/libstrongswan/crypto/certinfo.c | 48 --- src/libstrongswan/crypto/crl.c | 80 ++-- src/libstrongswan/crypto/crl.h | 9 + src/libstrongswan/crypto/ocsp.c | 2 +- src/libstrongswan/crypto/x509.c | 261 ++++++------ src/libstrongswan/crypto/x509.h | 76 +++- src/libstrongswan/library.h | 9 + src/libstrongswan/printf_hook.h | 16 - src/libstrongswan/utils/fetcher.c | 3 + src/libstrongswan/utils/host.c | 2 +- src/libstrongswan/utils/identification.c | 16 +- 24 files changed, 1450 insertions(+), 554 deletions(-) create mode 100644 src/libstrongswan/crypto/ac.c create mode 100644 src/libstrongswan/crypto/ac.h (limited to 'src/libstrongswan') diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index b103be193..292abc0a4 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -11,6 +11,7 @@ asn1/asn1.c asn1/asn1.h \ asn1/oid.c asn1/oid.h \ asn1/pem.c asn1/pem.h \ asn1/ttodata.c asn1/ttodata.h \ +crypto/ac.c crypto/ac.h \ crypto/ca.c crypto/ca.h \ crypto/certinfo.c crypto/certinfo.h \ crypto/crl.c crypto/crl.h \ diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in index e5c5c758e..015308449 100644 --- a/src/libstrongswan/Makefile.in +++ b/src/libstrongswan/Makefile.in @@ -60,7 +60,7 @@ am__DEPENDENCIES_1 = libstrongswan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libstrongswan_la_OBJECTS = library.lo chunk.lo debug.lo enum.lo \ - printf_hook.lo asn1.lo oid.lo pem.lo ttodata.lo ca.lo \ + printf_hook.lo asn1.lo oid.lo pem.lo ttodata.lo ac.lo ca.lo \ certinfo.lo crl.lo crypter.lo aes_cbc_crypter.lo \ des_crypter.lo diffie_hellman.lo hasher.lo sha1_hasher.lo \ sha2_hasher.lo md5_hasher.lo hmac.lo ocsp.lo fips_prf.lo \ @@ -129,6 +129,7 @@ LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ +LINUX_HEADERS = @LINUX_HEADERS@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ @@ -141,6 +142,7 @@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ RANLIB = @RANLIB@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ @@ -151,8 +153,12 @@ USE_LEAK_DETECTIVE_FALSE = @USE_LEAK_DETECTIVE_FALSE@ USE_LEAK_DETECTIVE_TRUE = @USE_LEAK_DETECTIVE_TRUE@ USE_LIBCURL_FALSE = @USE_LIBCURL_FALSE@ USE_LIBCURL_TRUE = @USE_LIBCURL_TRUE@ +USE_LIBDBUS_FALSE = @USE_LIBDBUS_FALSE@ +USE_LIBDBUS_TRUE = @USE_LIBDBUS_TRUE@ USE_LIBLDAP_FALSE = @USE_LIBLDAP_FALSE@ USE_LIBLDAP_TRUE = @USE_LIBLDAP_TRUE@ +USE_LIBXML_FALSE = @USE_LIBXML_FALSE@ +USE_LIBXML_TRUE = @USE_LIBXML_TRUE@ USE_NAT_TRANSPORT_FALSE = @USE_NAT_TRANSPORT_FALSE@ USE_NAT_TRANSPORT_TRUE = @USE_NAT_TRANSPORT_TRUE@ USE_SMARTCARD_FALSE = @USE_SMARTCARD_FALSE@ @@ -174,6 +180,7 @@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ +backenddir = @backenddir@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -183,6 +190,8 @@ build_vendor = @build_vendor@ confdir = @confdir@ datadir = @datadir@ datarootdir = @datarootdir@ +dbus_CFLAGS = @dbus_CFLAGS@ +dbus_LIBS = @dbus_LIBS@ docdir = @docdir@ dvidir = @dvidir@ eapdir = @eapdir@ @@ -196,9 +205,13 @@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ +interfacedir = @interfacedir@ ipsecdir = @ipsecdir@ +ipsecgid = @ipsecgid@ +ipsecuid = @ipsecuid@ libdir = @libdir@ libexecdir = @libexecdir@ +linuxdir = @linuxdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ @@ -213,6 +226,8 @@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ +xml_CFLAGS = @xml_CFLAGS@ +xml_LIBS = @xml_LIBS@ lib_LTLIBRARIES = libstrongswan.la libstrongswan_la_SOURCES = \ credential_store.h \ @@ -225,6 +240,7 @@ asn1/asn1.c asn1/asn1.h \ asn1/oid.c asn1/oid.h \ asn1/pem.c asn1/pem.h \ asn1/ttodata.c asn1/ttodata.h \ +crypto/ac.c crypto/ac.h \ crypto/ca.c crypto/ca.h \ crypto/certinfo.c crypto/certinfo.h \ crypto/crl.c crypto/crl.h \ @@ -333,6 +349,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ac.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aes_cbc_crypter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asn1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ca.Plo@am__quote@ @@ -421,6 +438,13 @@ ttodata.lo: asn1/ttodata.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ttodata.lo `test -f 'asn1/ttodata.c' || echo '$(srcdir)/'`asn1/ttodata.c +ac.lo: crypto/ac.c +@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ac.lo -MD -MP -MF "$(DEPDIR)/ac.Tpo" -c -o ac.lo `test -f 'crypto/ac.c' || echo '$(srcdir)/'`crypto/ac.c; \ +@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ac.Tpo" "$(DEPDIR)/ac.Plo"; else rm -f "$(DEPDIR)/ac.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='crypto/ac.c' object='ac.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ac.lo `test -f 'crypto/ac.c' || echo '$(srcdir)/'`crypto/ac.c + ca.lo: crypto/ca.c @am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ca.lo -MD -MP -MF "$(DEPDIR)/ca.Tpo" -c -o ca.lo `test -f 'crypto/ca.c' || echo '$(srcdir)/'`crypto/ca.c; \ @am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/ca.Tpo" "$(DEPDIR)/ca.Plo"; else rm -f "$(DEPDIR)/ca.Tpo"; exit 1; fi diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c index 91a6621d4..2a0aa4ff6 100644 --- a/src/libstrongswan/asn1/asn1.c +++ b/src/libstrongswan/asn1/asn1.c @@ -731,3 +731,43 @@ chunk_t timetoasn1(const time_t *time, asn1_t type) formatted_time.len = strlen(buf); return asn1_simple_object(type, formatted_time); } + +/** + * ASN.1 definition of time + */ +static const asn1Object_t timeObjects[] = { + { 0, "utcTime", ASN1_UTCTIME, ASN1_OPT|ASN1_BODY }, /* 0 */ + { 0, "end opt", ASN1_EOC, ASN1_END }, /* 1 */ + { 0, "generalizeTime",ASN1_GENERALIZEDTIME, ASN1_OPT|ASN1_BODY }, /* 2 */ + { 0, "end opt", ASN1_EOC, ASN1_END } /* 3 */ +}; +#define TIME_UTC 0 +#define TIME_GENERALIZED 2 +#define TIME_ROOF 4 + +/** + * extracts and converts a UTCTIME or GENERALIZEDTIME object + */ +time_t parse_time(chunk_t blob, int level0) +{ + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int objectID = 0; + + asn1_init(&ctx, blob, level0, FALSE, FALSE); + + while (objectID < TIME_ROOF) + { + if (!extract_object(timeObjects, &objectID, &object, &level, &ctx)) + return 0; + + if (objectID == TIME_UTC || objectID == TIME_GENERALIZED) + { + return asn1totime(&object, (objectID == TIME_UTC) + ? ASN1_UTCTIME : ASN1_GENERALIZEDTIME); + } + objectID++; + } + return 0; +} diff --git a/src/libstrongswan/asn1/asn1.h b/src/libstrongswan/asn1/asn1.h index 5ab519ec8..365ccb438 100644 --- a/src/libstrongswan/asn1/asn1.h +++ b/src/libstrongswan/asn1/asn1.h @@ -124,6 +124,8 @@ extern void asn1_init(asn1_ctx_t *ctx, chunk_t blob, u_int level0, bool implicit extern bool extract_object(asn1Object_t const *objects, u_int *objectID, chunk_t *object, u_int *level, asn1_ctx_t *ctx); extern bool parse_asn1_simple_object(chunk_t *object, asn1_t type, u_int level, const char* name); extern int parse_algorithmIdentifier(chunk_t blob, int level0, chunk_t *parameters); +extern time_t parse_time(chunk_t blob, int level0); + extern bool is_asn1(chunk_t blob); extern void code_asn1_length(size_t length, chunk_t *code); diff --git a/src/libstrongswan/asn1/oid.c b/src/libstrongswan/asn1/oid.c index 4b0632de2..48df1b7c4 100644 --- a/src/libstrongswan/asn1/oid.c +++ b/src/libstrongswan/asn1/oid.c @@ -28,7 +28,7 @@ const oid_t oid_names[] = { { 0x01, 0, 1, "pilotAttributeType" }, /* 15 */ { 0x01, 17, 0, "UID" }, /* 16 */ { 0x19, 0, 0, "DC" }, /* 17 */ - {0x55, 51, 1, "X.500" }, /* 18 */ + {0x55, 52, 1, "X.500" }, /* 18 */ { 0x04, 36, 1, "X.509" }, /* 19 */ { 0x03, 21, 0, "CN" }, /* 20 */ { 0x04, 22, 0, "S" }, /* 21 */ @@ -54,144 +54,145 @@ const oid_t oid_names[] = { { 0x11, 42, 0, "subjectAltName" }, /* 41 */ { 0x12, 43, 0, "issuerAltName" }, /* 42 */ { 0x13, 44, 0, "basicConstraints" }, /* 43 */ - { 0x15, 45, 0, "reasonCode" }, /* 44 */ - { 0x1F, 46, 0, "crlDistributionPoints" }, /* 45 */ - { 0x20, 47, 0, "certificatePolicies" }, /* 46 */ - { 0x23, 48, 0, "authorityKeyIdentifier" }, /* 47 */ - { 0x25, 49, 0, "extendedKeyUsage" }, /* 48 */ - { 0x37, 50, 0, "targetInformation" }, /* 49 */ - { 0x38, 0, 0, "noRevAvail" }, /* 50 */ - {0x2A, 88, 1, "" }, /* 51 */ - { 0x86, 0, 1, "" }, /* 52 */ - { 0x48, 0, 1, "" }, /* 53 */ - { 0x86, 0, 1, "" }, /* 54 */ - { 0xF7, 0, 1, "" }, /* 55 */ - { 0x0D, 0, 1, "RSADSI" }, /* 56 */ - { 0x01, 83, 1, "PKCS" }, /* 57 */ - { 0x01, 66, 1, "PKCS-1" }, /* 58 */ - { 0x01, 60, 0, "rsaEncryption" }, /* 59 */ - { 0x02, 61, 0, "md2WithRSAEncryption" }, /* 60 */ - { 0x04, 62, 0, "md5WithRSAEncryption" }, /* 61 */ - { 0x05, 63, 0, "sha-1WithRSAEncryption" }, /* 62 */ - { 0x0B, 64, 0, "sha256WithRSAEncryption"}, /* 63 */ - { 0x0C, 65, 0, "sha384WithRSAEncryption"}, /* 64 */ - { 0x0D, 0, 0, "sha512WithRSAEncryption"}, /* 65 */ - { 0x07, 73, 1, "PKCS-7" }, /* 66 */ - { 0x01, 68, 0, "data" }, /* 67 */ - { 0x02, 69, 0, "signedData" }, /* 68 */ - { 0x03, 70, 0, "envelopedData" }, /* 69 */ - { 0x04, 71, 0, "signedAndEnvelopedData" }, /* 70 */ - { 0x05, 72, 0, "digestedData" }, /* 71 */ - { 0x06, 0, 0, "encryptedData" }, /* 72 */ - { 0x09, 0, 1, "PKCS-9" }, /* 73 */ - { 0x01, 75, 0, "E" }, /* 74 */ - { 0x02, 76, 0, "unstructuredName" }, /* 75 */ - { 0x03, 77, 0, "contentType" }, /* 76 */ - { 0x04, 78, 0, "messageDigest" }, /* 77 */ - { 0x05, 79, 0, "signingTime" }, /* 78 */ - { 0x06, 80, 0, "counterSignature" }, /* 79 */ - { 0x07, 81, 0, "challengePassword" }, /* 80 */ - { 0x08, 82, 0, "unstructuredAddress" }, /* 81 */ - { 0x0E, 0, 0, "extensionRequest" }, /* 82 */ - { 0x02, 86, 1, "digestAlgorithm" }, /* 83 */ - { 0x02, 85, 0, "md2" }, /* 84 */ - { 0x05, 0, 0, "md5" }, /* 85 */ - { 0x03, 0, 1, "encryptionAlgorithm" }, /* 86 */ - { 0x07, 0, 0, "3des-ede-cbc" }, /* 87 */ - {0x2B, 149, 1, "" }, /* 88 */ - { 0x06, 136, 1, "dod" }, /* 89 */ - { 0x01, 0, 1, "internet" }, /* 90 */ - { 0x04, 105, 1, "private" }, /* 91 */ - { 0x01, 0, 1, "enterprise" }, /* 92 */ - { 0x82, 98, 1, "" }, /* 93 */ - { 0x37, 0, 1, "Microsoft" }, /* 94 */ - { 0x0A, 0, 1, "" }, /* 95 */ - { 0x03, 0, 1, "" }, /* 96 */ - { 0x03, 0, 0, "msSGC" }, /* 97 */ - { 0x89, 0, 1, "" }, /* 98 */ - { 0x31, 0, 1, "" }, /* 99 */ - { 0x01, 0, 1, "" }, /* 100 */ - { 0x01, 0, 1, "" }, /* 101 */ - { 0x02, 0, 1, "" }, /* 102 */ - { 0x02, 104, 0, "" }, /* 103 */ - { 0x4B, 0, 0, "TCGID" }, /* 104 */ - { 0x05, 0, 1, "security" }, /* 105 */ - { 0x05, 0, 1, "mechanisms" }, /* 106 */ - { 0x07, 0, 1, "id-pkix" }, /* 107 */ - { 0x01, 110, 1, "id-pe" }, /* 108 */ - { 0x01, 0, 0, "authorityInfoAccess" }, /* 109 */ - { 0x03, 120, 1, "id-kp" }, /* 110 */ - { 0x01, 112, 0, "serverAuth" }, /* 111 */ - { 0x02, 113, 0, "clientAuth" }, /* 112 */ - { 0x03, 114, 0, "codeSigning" }, /* 113 */ - { 0x04, 115, 0, "emailProtection" }, /* 114 */ - { 0x05, 116, 0, "ipsecEndSystem" }, /* 115 */ - { 0x06, 117, 0, "ipsecTunnel" }, /* 116 */ - { 0x07, 118, 0, "ipsecUser" }, /* 117 */ - { 0x08, 119, 0, "timeStamping" }, /* 118 */ - { 0x09, 0, 0, "ocspSigning" }, /* 119 */ - { 0x08, 122, 1, "id-otherNames" }, /* 120 */ - { 0x05, 0, 0, "xmppAddr" }, /* 121 */ - { 0x0A, 127, 1, "id-aca" }, /* 122 */ - { 0x01, 124, 0, "authenticationInfo" }, /* 123 */ - { 0x02, 125, 0, "accessIdentity" }, /* 124 */ - { 0x03, 126, 0, "chargingIdentity" }, /* 125 */ - { 0x04, 0, 0, "group" }, /* 126 */ - { 0x30, 0, 1, "id-ad" }, /* 127 */ - { 0x01, 0, 1, "ocsp" }, /* 128 */ - { 0x01, 130, 0, "basic" }, /* 129 */ - { 0x02, 131, 0, "nonce" }, /* 130 */ - { 0x03, 132, 0, "crl" }, /* 131 */ - { 0x04, 133, 0, "response" }, /* 132 */ - { 0x05, 134, 0, "noCheck" }, /* 133 */ - { 0x06, 135, 0, "archiveCutoff" }, /* 134 */ - { 0x07, 0, 0, "serviceLocator" }, /* 135 */ - { 0x0E, 142, 1, "oiw" }, /* 136 */ - { 0x03, 0, 1, "secsig" }, /* 137 */ - { 0x02, 0, 1, "algorithms" }, /* 138 */ - { 0x07, 140, 0, "des-cbc" }, /* 139 */ - { 0x1A, 141, 0, "sha-1" }, /* 140 */ - { 0x1D, 0, 0, "sha-1WithRSASignature" }, /* 141 */ - { 0x24, 0, 1, "TeleTrusT" }, /* 142 */ - { 0x03, 0, 1, "algorithm" }, /* 143 */ - { 0x03, 0, 1, "signatureAlgorithm" }, /* 144 */ - { 0x01, 0, 1, "rsaSignature" }, /* 145 */ - { 0x02, 147, 0, "rsaSigWithripemd160" }, /* 146 */ - { 0x03, 148, 0, "rsaSigWithripemd128" }, /* 147 */ - { 0x04, 0, 0, "rsaSigWithripemd256" }, /* 148 */ - {0x60, 0, 1, "" }, /* 149 */ - { 0x86, 0, 1, "" }, /* 150 */ - { 0x48, 0, 1, "" }, /* 151 */ - { 0x01, 0, 1, "organization" }, /* 152 */ - { 0x65, 160, 1, "gov" }, /* 153 */ - { 0x03, 0, 1, "csor" }, /* 154 */ - { 0x04, 0, 1, "nistalgorithm" }, /* 155 */ - { 0x02, 0, 1, "hashalgs" }, /* 156 */ - { 0x01, 158, 0, "id-SHA-256" }, /* 157 */ - { 0x02, 159, 0, "id-SHA-384" }, /* 158 */ - { 0x03, 0, 0, "id-SHA-512" }, /* 159 */ - { 0x86, 0, 1, "" }, /* 160 */ - { 0xf8, 0, 1, "" }, /* 161 */ - { 0x42, 174, 1, "netscape" }, /* 162 */ - { 0x01, 169, 1, "" }, /* 163 */ - { 0x01, 165, 0, "nsCertType" }, /* 164 */ - { 0x03, 166, 0, "nsRevocationUrl" }, /* 165 */ - { 0x04, 167, 0, "nsCaRevocationUrl" }, /* 166 */ - { 0x08, 168, 0, "nsCaPolicyUrl" }, /* 167 */ - { 0x0d, 0, 0, "nsComment" }, /* 168 */ - { 0x03, 172, 1, "directory" }, /* 169 */ - { 0x01, 0, 1, "" }, /* 170 */ - { 0x03, 0, 0, "employeeNumber" }, /* 171 */ - { 0x04, 0, 1, "policy" }, /* 172 */ - { 0x01, 0, 0, "nsSGC" }, /* 173 */ - { 0x45, 0, 1, "verisign" }, /* 174 */ - { 0x01, 0, 1, "pki" }, /* 175 */ - { 0x09, 0, 1, "attributes" }, /* 176 */ - { 0x02, 178, 0, "messageType" }, /* 177 */ - { 0x03, 179, 0, "pkiStatus" }, /* 178 */ - { 0x04, 180, 0, "failInfo" }, /* 179 */ - { 0x05, 181, 0, "senderNonce" }, /* 180 */ - { 0x06, 182, 0, "recipientNonce" }, /* 181 */ - { 0x07, 183, 0, "transID" }, /* 182 */ - { 0x08, 0, 0, "extensionReq" } /* 183 */ + { 0x14, 45, 0, "crlNumber" }, /* 44 */ + { 0x15, 46, 0, "reasonCode" }, /* 45 */ + { 0x1F, 47, 0, "crlDistributionPoints" }, /* 46 */ + { 0x20, 48, 0, "certificatePolicies" }, /* 47 */ + { 0x23, 49, 0, "authorityKeyIdentifier" }, /* 48 */ + { 0x25, 50, 0, "extendedKeyUsage" }, /* 49 */ + { 0x37, 51, 0, "targetInformation" }, /* 50 */ + { 0x38, 0, 0, "noRevAvail" }, /* 51 */ + {0x2A, 89, 1, "" }, /* 52 */ + { 0x86, 0, 1, "" }, /* 53 */ + { 0x48, 0, 1, "" }, /* 54 */ + { 0x86, 0, 1, "" }, /* 55 */ + { 0xF7, 0, 1, "" }, /* 56 */ + { 0x0D, 0, 1, "RSADSI" }, /* 57 */ + { 0x01, 84, 1, "PKCS" }, /* 58 */ + { 0x01, 67, 1, "PKCS-1" }, /* 59 */ + { 0x01, 61, 0, "rsaEncryption" }, /* 60 */ + { 0x02, 62, 0, "md2WithRSAEncryption" }, /* 61 */ + { 0x04, 63, 0, "md5WithRSAEncryption" }, /* 62 */ + { 0x05, 64, 0, "sha-1WithRSAEncryption" }, /* 63 */ + { 0x0B, 65, 0, "sha256WithRSAEncryption"}, /* 64 */ + { 0x0C, 66, 0, "sha384WithRSAEncryption"}, /* 65 */ + { 0x0D, 0, 0, "sha512WithRSAEncryption"}, /* 66 */ + { 0x07, 74, 1, "PKCS-7" }, /* 67 */ + { 0x01, 69, 0, "data" }, /* 68 */ + { 0x02, 70, 0, "signedData" }, /* 69 */ + { 0x03, 71, 0, "envelopedData" }, /* 70 */ + { 0x04, 72, 0, "signedAndEnvelopedData" }, /* 71 */ + { 0x05, 73, 0, "digestedData" }, /* 72 */ + { 0x06, 0, 0, "encryptedData" }, /* 73 */ + { 0x09, 0, 1, "PKCS-9" }, /* 74 */ + { 0x01, 76, 0, "E" }, /* 75 */ + { 0x02, 77, 0, "unstructuredName" }, /* 76 */ + { 0x03, 78, 0, "contentType" }, /* 77 */ + { 0x04, 79, 0, "messageDigest" }, /* 78 */ + { 0x05, 80, 0, "signingTime" }, /* 79 */ + { 0x06, 81, 0, "counterSignature" }, /* 80 */ + { 0x07, 82, 0, "challengePassword" }, /* 81 */ + { 0x08, 83, 0, "unstructuredAddress" }, /* 82 */ + { 0x0E, 0, 0, "extensionRequest" }, /* 83 */ + { 0x02, 87, 1, "digestAlgorithm" }, /* 84 */ + { 0x02, 86, 0, "md2" }, /* 85 */ + { 0x05, 0, 0, "md5" }, /* 86 */ + { 0x03, 0, 1, "encryptionAlgorithm" }, /* 87 */ + { 0x07, 0, 0, "3des-ede-cbc" }, /* 88 */ + {0x2B, 150, 1, "" }, /* 89 */ + { 0x06, 137, 1, "dod" }, /* 90 */ + { 0x01, 0, 1, "internet" }, /* 91 */ + { 0x04, 106, 1, "private" }, /* 92 */ + { 0x01, 0, 1, "enterprise" }, /* 93 */ + { 0x82, 99, 1, "" }, /* 94 */ + { 0x37, 0, 1, "Microsoft" }, /* 95 */ + { 0x0A, 0, 1, "" }, /* 96 */ + { 0x03, 0, 1, "" }, /* 97 */ + { 0x03, 0, 0, "msSGC" }, /* 98 */ + { 0x89, 0, 1, "" }, /* 99 */ + { 0x31, 0, 1, "" }, /* 100 */ + { 0x01, 0, 1, "" }, /* 101 */ + { 0x01, 0, 1, "" }, /* 102 */ + { 0x02, 0, 1, "" }, /* 103 */ + { 0x02, 105, 0, "" }, /* 104 */ + { 0x4B, 0, 0, "TCGID" }, /* 105 */ + { 0x05, 0, 1, "security" }, /* 106 */ + { 0x05, 0, 1, "mechanisms" }, /* 107 */ + { 0x07, 0, 1, "id-pkix" }, /* 108 */ + { 0x01, 111, 1, "id-pe" }, /* 109 */ + { 0x01, 0, 0, "authorityInfoAccess" }, /* 110 */ + { 0x03, 121, 1, "id-kp" }, /* 111 */ + { 0x01, 113, 0, "serverAuth" }, /* 112 */ + { 0x02, 114, 0, "clientAuth" }, /* 113 */ + { 0x03, 115, 0, "codeSigning" }, /* 114 */ + { 0x04, 116, 0, "emailProtection" }, /* 115 */ + { 0x05, 117, 0, "ipsecEndSystem" }, /* 116 */ + { 0x06, 118, 0, "ipsecTunnel" }, /* 117 */ + { 0x07, 119, 0, "ipsecUser" }, /* 118 */ + { 0x08, 120, 0, "timeStamping" }, /* 119 */ + { 0x09, 0, 0, "ocspSigning" }, /* 120 */ + { 0x08, 123, 1, "id-otherNames" }, /* 121 */ + { 0x05, 0, 0, "xmppAddr" }, /* 122 */ + { 0x0A, 128, 1, "id-aca" }, /* 123 */ + { 0x01, 125, 0, "authenticationInfo" }, /* 124 */ + { 0x02, 126, 0, "accessIdentity" }, /* 125 */ + { 0x03, 127, 0, "chargingIdentity" }, /* 126 */ + { 0x04, 0, 0, "group" }, /* 127 */ + { 0x30, 0, 1, "id-ad" }, /* 128 */ + { 0x01, 0, 1, "ocsp" }, /* 129 */ + { 0x01, 131, 0, "basic" }, /* 130 */ + { 0x02, 132, 0, "nonce" }, /* 131 */ + { 0x03, 133, 0, "crl" }, /* 132 */ + { 0x04, 134, 0, "response" }, /* 133 */ + { 0x05, 135, 0, "noCheck" }, /* 134 */ + { 0x06, 136, 0, "archiveCutoff" }, /* 135 */ + { 0x07, 0, 0, "serviceLocator" }, /* 136 */ + { 0x0E, 143, 1, "oiw" }, /* 137 */ + { 0x03, 0, 1, "secsig" }, /* 138 */ + { 0x02, 0, 1, "algorithms" }, /* 139 */ + { 0x07, 141, 0, "des-cbc" }, /* 140 */ + { 0x1A, 142, 0, "sha-1" }, /* 141 */ + { 0x1D, 0, 0, "sha-1WithRSASignature" }, /* 142 */ + { 0x24, 0, 1, "TeleTrusT" }, /* 143 */ + { 0x03, 0, 1, "algorithm" }, /* 144 */ + { 0x03, 0, 1, "signatureAlgorithm" }, /* 145 */ + { 0x01, 0, 1, "rsaSignature" }, /* 146 */ + { 0x02, 148, 0, "rsaSigWithripemd160" }, /* 147 */ + { 0x03, 149, 0, "rsaSigWithripemd128" }, /* 148 */ + { 0x04, 0, 0, "rsaSigWithripemd256" }, /* 149 */ + {0x60, 0, 1, "" }, /* 150 */ + { 0x86, 0, 1, "" }, /* 151 */ + { 0x48, 0, 1, "" }, /* 152 */ + { 0x01, 0, 1, "organization" }, /* 153 */ + { 0x65, 161, 1, "gov" }, /* 154 */ + { 0x03, 0, 1, "csor" }, /* 155 */ + { 0x04, 0, 1, "nistalgorithm" }, /* 156 */ + { 0x02, 0, 1, "hashalgs" }, /* 157 */ + { 0x01, 159, 0, "id-SHA-256" }, /* 158 */ + { 0x02, 160, 0, "id-SHA-384" }, /* 159 */ + { 0x03, 0, 0, "id-SHA-512" }, /* 160 */ + { 0x86, 0, 1, "" }, /* 161 */ + { 0xf8, 0, 1, "" }, /* 162 */ + { 0x42, 175, 1, "netscape" }, /* 163 */ + { 0x01, 170, 1, "" }, /* 164 */ + { 0x01, 166, 0, "nsCertType" }, /* 165 */ + { 0x03, 167, 0, "nsRevocationUrl" }, /* 166 */ + { 0x04, 168, 0, "nsCaRevocationUrl" }, /* 167 */ + { 0x08, 169, 0, "nsCaPolicyUrl" }, /* 168 */ + { 0x0d, 0, 0, "nsComment" }, /* 169 */ + { 0x03, 173, 1, "directory" }, /* 170 */ + { 0x01, 0, 1, "" }, /* 171 */ + { 0x03, 0, 0, "employeeNumber" }, /* 172 */ + { 0x04, 0, 1, "policy" }, /* 173 */ + { 0x01, 0, 0, "nsSGC" }, /* 174 */ + { 0x45, 0, 1, "verisign" }, /* 175 */ + { 0x01, 0, 1, "pki" }, /* 176 */ + { 0x09, 0, 1, "attributes" }, /* 177 */ + { 0x02, 179, 0, "messageType" }, /* 178 */ + { 0x03, 180, 0, "pkiStatus" }, /* 179 */ + { 0x04, 181, 0, "failInfo" }, /* 180 */ + { 0x05, 182, 0, "senderNonce" }, /* 181 */ + { 0x06, 183, 0, "recipientNonce" }, /* 182 */ + { 0x07, 184, 0, "transID" }, /* 183 */ + { 0x08, 0, 0, "extensionReq" } /* 184 */ }; diff --git a/src/libstrongswan/asn1/oid.h b/src/libstrongswan/asn1/oid.h index f85997159..49260c9f4 100644 --- a/src/libstrongswan/asn1/oid.h +++ b/src/libstrongswan/asn1/oid.h @@ -22,59 +22,63 @@ extern const oid_t oid_names[]; #define OID_SUBJECT_KEY_ID 38 #define OID_SUBJECT_ALT_NAME 41 #define OID_BASIC_CONSTRAINTS 43 -#define OID_CRL_REASON_CODE 44 -#define OID_CRL_DISTRIBUTION_POINTS 45 -#define OID_AUTHORITY_KEY_ID 47 -#define OID_EXTENDED_KEY_USAGE 48 -#define OID_TARGET_INFORMATION 49 -#define OID_NO_REV_AVAIL 50 -#define OID_RSA_ENCRYPTION 59 -#define OID_MD2_WITH_RSA 60 -#define OID_MD5_WITH_RSA 61 -#define OID_SHA1_WITH_RSA 62 -#define OID_SHA256_WITH_RSA 63 -#define OID_SHA384_WITH_RSA 64 -#define OID_SHA512_WITH_RSA 65 -#define OID_PKCS7_DATA 67 -#define OID_PKCS7_SIGNED_DATA 68 -#define OID_PKCS7_ENVELOPED_DATA 69 -#define OID_PKCS7_SIGNED_ENVELOPED_DATA 70 -#define OID_PKCS7_DIGESTED_DATA 71 -#define OID_PKCS7_ENCRYPTED_DATA 72 -#define OID_PKCS9_EMAIL 74 -#define OID_PKCS9_CONTENT_TYPE 76 -#define OID_PKCS9_MESSAGE_DIGEST 77 -#define OID_PKCS9_SIGNING_TIME 78 -#define OID_MD2 84 -#define OID_MD5 85 -#define OID_3DES_EDE_CBC 87 -#define OID_AUTHORITY_INFO_ACCESS 109 -#define OID_OCSP_SIGNING 119 -#define OID_XMPP_ADDR 121 -#define OID_AUTHENTICATION_INFO 123 -#define OID_ACCESS_IDENTITY 124 -#define OID_CHARGING_IDENTITY 125 -#define OID_GROUP 126 -#define OID_OCSP 128 -#define OID_BASIC 129 -#define OID_NONCE 130 -#define OID_CRL 131 -#define OID_RESPONSE 132 -#define OID_NO_CHECK 133 -#define OID_ARCHIVE_CUTOFF 134 -#define OID_SERVICE_LOCATOR 135 -#define OID_DES_CBC 139 -#define OID_SHA1 140 -#define OID_SHA1_WITH_RSA_OIW 141 -#define OID_NS_REVOCATION_URL 165 -#define OID_NS_CA_REVOCATION_URL 166 -#define OID_NS_CA_POLICY_URL 167 -#define OID_NS_COMMENT 168 -#define OID_PKI_MESSAGE_TYPE 177 -#define OID_PKI_STATUS 178 -#define OID_PKI_FAIL_INFO 179 -#define OID_PKI_SENDER_NONCE 180 -#define OID_PKI_RECIPIENT_NONCE 181 -#define OID_PKI_TRANS_ID 182 +#define OID_CRL_NUMBER 44 +#define OID_CRL_REASON_CODE 45 +#define OID_CRL_DISTRIBUTION_POINTS 46 +#define OID_AUTHORITY_KEY_ID 48 +#define OID_EXTENDED_KEY_USAGE 49 +#define OID_TARGET_INFORMATION 50 +#define OID_NO_REV_AVAIL 51 +#define OID_RSA_ENCRYPTION 60 +#define OID_MD2_WITH_RSA 61 +#define OID_MD5_WITH_RSA 62 +#define OID_SHA1_WITH_RSA 63 +#define OID_SHA256_WITH_RSA 64 +#define OID_SHA384_WITH_RSA 65 +#define OID_SHA512_WITH_RSA 66 +#define OID_PKCS7_DATA 68 +#define OID_PKCS7_SIGNED_DATA 69 +#define OID_PKCS7_ENVELOPED_DATA 70 +#define OID_PKCS7_SIGNED_ENVELOPED_DATA 71 +#define OID_PKCS7_DIGESTED_DATA 72 +#define OID_PKCS7_ENCRYPTED_DATA 73 +#define OID_PKCS9_EMAIL 75 +#define OID_PKCS9_CONTENT_TYPE 77 +#define OID_PKCS9_MESSAGE_DIGEST 78 +#define OID_PKCS9_SIGNING_TIME 79 +#define OID_MD2 85 +#define OID_MD5 86 +#define OID_3DES_EDE_CBC 88 +#define OID_AUTHORITY_INFO_ACCESS 110 +#define OID_OCSP_SIGNING 120 +#define OID_XMPP_ADDR 122 +#define OID_AUTHENTICATION_INFO 124 +#define OID_ACCESS_IDENTITY 125 +#define OID_CHARGING_IDENTITY 126 +#define OID_GROUP 127 +#define OID_OCSP 129 +#define OID_BASIC 130 +#define OID_NONCE 131 +#define OID_CRL 132 +#define OID_RESPONSE 133 +#define OID_NO_CHECK 134 +#define OID_ARCHIVE_CUTOFF 135 +#define OID_SERVICE_LOCATOR 136 +#define OID_DES_CBC 140 +#define OID_SHA1 141 +#define OID_SHA1_WITH_RSA_OIW 142 +#define OID_SHA256 158 +#define OID_SHA384 159 +#define OID_SHA512 160 +#define OID_NS_REVOCATION_URL 166 +#define OID_NS_CA_REVOCATION_URL 167 +#define OID_NS_CA_POLICY_URL 168 +#define OID_NS_COMMENT 169 +#define OID_PKI_MESSAGE_TYPE 178 +#define OID_PKI_STATUS 179 +#define OID_PKI_FAIL_INFO 180 +#define OID_PKI_SENDER_NONCE 181 +#define OID_PKI_RECIPIENT_NONCE 182 +#define OID_PKI_TRANS_ID 183 #endif /* OID_H_ */ diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt index eed46d59d..2b3c96ae3 100644 --- a/src/libstrongswan/asn1/oid.txt +++ b/src/libstrongswan/asn1/oid.txt @@ -42,6 +42,7 @@ 0x11 "subjectAltName" OID_SUBJECT_ALT_NAME 0x12 "issuerAltName" 0x13 "basicConstraints" OID_BASIC_CONSTRAINTS + 0x14 "crlNumber" OID_CRL_NUMBER 0x15 "reasonCode" OID_CRL_REASON_CODE 0x1F "crlDistributionPoints" OID_CRL_DISTRIBUTION_POINTS 0x20 "certificatePolicies" @@ -155,9 +156,9 @@ 0x03 "csor" 0x04 "nistalgorithm" 0x02 "hashalgs" - 0x01 "id-SHA-256" - 0x02 "id-SHA-384" - 0x03 "id-SHA-512" + 0x01 "id-SHA-256" OID_SHA256 + 0x02 "id-SHA-384" OID_SHA384 + 0x03 "id-SHA-512" OID_SHA512 0x86 "" 0xf8 "" 0x42 "netscape" diff --git a/src/libstrongswan/chunk.c b/src/libstrongswan/chunk.c index cba823c22..d70e1723f 100644 --- a/src/libstrongswan/chunk.c +++ b/src/libstrongswan/chunk.c @@ -22,6 +22,7 @@ */ #include +#include #include "chunk.h" diff --git a/src/libstrongswan/credential_store.h b/src/libstrongswan/credential_store.h index 5d51981ec..dcbe43f52 100755 --- a/src/libstrongswan/credential_store.h +++ b/src/libstrongswan/credential_store.h @@ -87,15 +87,6 @@ struct credential_store_t { */ rsa_public_key_t* (*get_rsa_public_key) (credential_store_t *this, identification_t *id); - /** - * @brief Returns the RSA public key of a specific ID if is trusted - * - * @param this calling object - * @param id identification_t object identifiying the key. - * @return public key, or NULL if not found or not trusted - */ - rsa_public_key_t* (*get_trusted_public_key) (credential_store_t *this, identification_t *id); - /** * @brief Returns the RSA private key belonging to an RSA public key * @@ -151,16 +142,29 @@ struct credential_store_t { * @param cert certificate for which issuer ca info is required * @return ca info, or NULL if not found */ - ca_info_t* (*get_issuer) (credential_store_t *this, const x509_t* cert); + ca_info_t* (*get_issuer) (credential_store_t *this, x509_t* cert); + /** + * @brief Verify an RSA signature given the ID of the signer + * + * @param this calling object + * @param hash hash value to be verified. + * @param sig signature to be verified. + * @param id identification_t object identifiying the signer. + * @param issuer_p issuer of the signer's certificate (if not self-signed). + * @return status of the verification - SUCCESS if successful + */ + status_t (*verify_signature) (credential_store_t *this, chunk_t hash, chunk_t sig, identification_t *id, ca_info_t **issuer_p); + /** * @brief Verify an X.509 certificate up to trust anchor without any status checks * * @param this calling object + * @param label label characterizing the certificate to be verified * @param cert certificate to be verified * @return TRUE if trusted */ - bool (*is_trusted) (credential_store_t *this, x509_t *cert); + bool (*is_trusted) (credential_store_t *this, const char *label, x509_t *cert); /** * @brief Verify an X.509 certificate up to trust anchor including status checks @@ -196,8 +200,9 @@ struct credential_store_t { * * @param this calling object * @param ca_info ca info record to be added + * @return pointer to the added or already existing ca_info_t record */ - void (*add_ca_info) (credential_store_t *this, ca_info_t *ca_info); + ca_info_t* (*add_ca_info) (credential_store_t *this, ca_info_t *ca_info); /** * @brief Release a ca info record with a given name. @@ -243,6 +248,24 @@ struct credential_store_t { */ void (*load_ca_certificates) (credential_store_t *this); + /** + * @brief Loads authorization authority certificates from a default directory. + * + * Certificates in both DER and PEM format are accepted + * + * @param this calling object + */ + void (*load_aa_certificates) (credential_store_t *this); + + /** + * @brief Loads attribute certificates from a default directory. + * + * Certificates in both DER and PEM format are accepted + * + * @param this calling object + */ + void (*load_attr_certificates) (credential_store_t *this); + /** * @brief Loads ocsp certificates from a default directory. * diff --git a/src/libstrongswan/crypto/ac.c b/src/libstrongswan/crypto/ac.c new file mode 100644 index 000000000..47605e9e1 --- /dev/null +++ b/src/libstrongswan/crypto/ac.c @@ -0,0 +1,665 @@ +/** + * @file ac.c + * + * @brief Implementation of x509ac_t. + * + */ + +/* + * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler + * Copyright (C) 2003 Martin Berner, Lukas Suter + * Copyright (C) 2007 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 . + * + * 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 +#include + +#include +#include +#include + +#include "ac.h" + +typedef struct private_x509ac_t private_x509ac_t; + +/** + * Private data of a x509ac_t object. + */ +struct private_x509ac_t { + /** + * Public interface for this attribute certificate. + */ + x509ac_t public; + + /** + * Time when attribute certificate was installed + */ + time_t installed; + + /** + * X.509 attribute certificate in DER format + */ + chunk_t certificate; + + /** + * X.509 attribute certificate body over which signature is computed + */ + chunk_t certificateInfo; + + /** + * Version of the X.509 attribute certificate + */ + u_int version; + + /** + * Serial number of the X.509 attribute certificate + */ + chunk_t serialNumber; + + /** + * ID representing the issuer of the holder certificate + */ + identification_t *holderIssuer; + + /** + * Serial number of the holder certificate + */ + chunk_t holderSerial; + + /** + * ID representing the holder + */ + identification_t *entityName; + + /** + * ID representing the attribute certificate issuer + */ + identification_t *issuerName; + + /** + * Signature algorithm + */ + int sigAlg; + + /** + * Start time of certificate validity + */ + time_t notBefore; + + /** + * End time of certificate validity + */ + time_t notAfter; + + /** + * List of charging attributes + */ + linked_list_t *charging; + + /** + * List of groub attributes + */ + linked_list_t *groups; + + /** + * Authority Key Identifier + */ + chunk_t authKeyID; + + /** + * Authority Key Serial Number + */ + chunk_t authKeySerialNumber; + + /** + * No revocation information available + */ + bool noRevAvail; + + /** + * Signature algorithm (must be identical to sigAlg) + */ + int algorithm; + + /** + * Signature + */ + chunk_t signature; +}; + +/** + * definition of ietfAttribute kinds + */ +typedef enum { + IETF_ATTRIBUTE_OCTETS = 0, + IETF_ATTRIBUTE_OID = 1, + IETF_ATTRIBUTE_STRING = 2 +} ietfAttribute_t; + +/** + * access structure for an ietfAttribute + */ +typedef struct ietfAttr_t ietfAttr_t; + +struct ietfAttr_t { + /** + * IETF attribute kind + */ + ietfAttribute_t kind; + + /** + * IETF attribute valuse + */ + chunk_t value; + + /** + * Destroys the ietfAttr_t object. + * + * @param this ietfAttr_t to destroy + */ + void (*destroy) (ietfAttr_t *this); +}; + +/** + * Destroys an ietfAttr_t object + */ +static void ietfAttr_destroy(ietfAttr_t *this) +{ + free(this->value.ptr); + free(this); +} + +/** + * Creates an ietfAttr_t object. + */ +ietfAttr_t *ietfAttr_create(ietfAttribute_t kind, chunk_t value) +{ + ietfAttr_t *this = malloc_thing(ietfAttr_t); + + /* initialize */ + this->kind = kind; + this->value = chunk_clone(value); + + /* function */ + this->destroy = ietfAttr_destroy; + + return this; +} + +/** + * ASN.1 definition of ietfAttrSyntax + */ +static const asn1Object_t ietfAttrSyntaxObjects[] = +{ + { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_BODY }, /* 1 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ + { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */ + { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT | + ASN1_BODY }, /* 4 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */ + { 2, "oid", ASN1_OID, ASN1_OPT | + ASN1_BODY }, /* 6 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */ + { 2, "string", ASN1_UTF8STRING, ASN1_OPT | + ASN1_BODY }, /* 8 */ + { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */ + { 1, "end loop", ASN1_EOC, ASN1_END } /* 10 */ +}; + +#define IETF_ATTR_OCTETS 4 +#define IETF_ATTR_OID 6 +#define IETF_ATTR_STRING 8 +#define IETF_ATTR_ROOF 11 + +/** + * ASN.1 definition of roleSyntax + */ +static const asn1Object_t roleSyntaxObjects[] = +{ + { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */ + { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT | + ASN1_OBJ }, /* 1 */ + { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */ + { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ } /* 3 */ +}; + +#define ROLE_ROOF 4 + +/** + * ASN.1 definition of an X509 attribute certificate + */ +static const asn1Object_t acObjects[] = +{ + { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ + { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */ + { 2, "version", ASN1_INTEGER, ASN1_DEF | + ASN1_BODY }, /* 2 */ + { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */ + { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */ + { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */ + { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */ + { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | + ASN1_BODY }, /* 7 */ + { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */ + { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT | + ASN1_OBJ }, /* 10 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */ + { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */ + { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13*/ + { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT | + ASN1_BODY }, /* 14 */ + { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15*/ + { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */ + { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */ + { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT | + ASN1_OBJ }, /* 19 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */ + { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */ + { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */ + { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */ + { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */ + { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT | + ASN1_BODY }, /* 25 */ + { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */ + { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */ + { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */ + { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */ + { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT | + ASN1_BODY }, /* 31 */ + { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */ + { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */ + { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */ + { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */ + { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */ + { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */ + { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */ + { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */ + { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */ + { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */ + { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */ + { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */ + { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */ + { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */ + { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */ + { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */ + { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */ + { 4, "critical", ASN1_BOOLEAN, ASN1_DEF | + ASN1_BODY }, /* 50 */ + { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */ + { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */ + { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */ + { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 54 */ +}; + +#define AC_OBJ_CERTIFICATE 0 +#define AC_OBJ_CERTIFICATE_INFO 1 +#define AC_OBJ_VERSION 2 +#define AC_OBJ_HOLDER_ISSUER 5 +#define AC_OBJ_HOLDER_SERIAL 6 +#define AC_OBJ_ENTITY_NAME 10 +#define AC_OBJ_ISSUER_NAME 19 +#define AC_OBJ_ISSUER 23 +#define AC_OBJ_SIG_ALG 35 +#define AC_OBJ_SERIAL_NUMBER 36 +#define AC_OBJ_NOT_BEFORE 38 +#define AC_OBJ_NOT_AFTER 39 +#define AC_OBJ_ATTRIBUTE_TYPE 42 +#define AC_OBJ_ATTRIBUTE_VALUE 44 +#define AC_OBJ_EXTN_ID 49 +#define AC_OBJ_CRITICAL 50 +#define AC_OBJ_EXTN_VALUE 51 +#define AC_OBJ_ALGORITHM 53 +#define AC_OBJ_SIGNATURE 54 +#define AC_OBJ_ROOF 55 + +/** + * Implements x509ac_t.is_valid + */ +static err_t is_valid(const private_x509ac_t *this, time_t *until) +{ + time_t current_time = time(NULL); + + DBG2(" not before : %T", &this->notBefore); + DBG2(" current time: %T", ¤t_time); + DBG2(" not after : %T", &this->notAfter); + + if (until != NULL && + (*until == UNDEFINED_TIME || this->notAfter < *until)) + { + *until = this->notAfter; + } + if (current_time < this->notBefore) + { + return "is not valid yet"; + } + if (current_time > this->notAfter) + { + return "has expired"; + } + DBG2(" attribute certificate is valid"); + return NULL; +} + +/** + * parses a directoryName + */ +static bool parse_directoryName(chunk_t blob, int level, bool implicit, identification_t **name) +{ + bool has_directoryName; + linked_list_t *list = linked_list_create(); + + parse_generalNames(blob, level, implicit, list); + has_directoryName = list->get_count(list) > 0; + + if (has_directoryName) + { + iterator_t *iterator = list->create_iterator(list, TRUE); + identification_t *directoryName; + bool first = TRUE; + + while (iterator->iterate(iterator, (void**)&directoryName)) + { + if (first) + { + *name = directoryName; + first = FALSE; + } + else + { + DBG1("more than one directory name - first selected"); + directoryName->destroy(directoryName); + } + } + iterator->destroy(iterator); + } + else + { + DBG1("no directoryName found"); + } + + list->destroy(list); + return has_directoryName; +} + +/** + * parses ietfAttrSyntax + */ +static void parse_ietfAttrSyntax(chunk_t blob, int level0, linked_list_t *list) +{ + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int objectID = 0; + + asn1_init(&ctx, blob, level0, FALSE, FALSE); + + while (objectID < IETF_ATTR_ROOF) + { + if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx)) + { + return; + } + + switch (objectID) + { + case IETF_ATTR_OCTETS: + case IETF_ATTR_OID: + case IETF_ATTR_STRING: + { + ietfAttribute_t kind = (objectID - IETF_ATTR_OCTETS) / 2; + ietfAttr_t *attr = ietfAttr_create(kind, object); + list->insert_last(list, (void *)attr); + } + break; + default: + break; + } + objectID++; + } +} + +/** + * parses roleSyntax + */ +static void parse_roleSyntax(chunk_t blob, int level0) +{ + asn1_ctx_t ctx; + chunk_t object; + u_int level; + int objectID = 0; + + asn1_init(&ctx, blob, level0, FALSE, FALSE); + while (objectID < ROLE_ROOF) + { + if (!extract_object(roleSyntaxObjects, &objectID, &object, &level, &ctx)) + { + return; + } + + switch (objectID) + { + default: + break; + } + objectID++; + } +} + +/** + * Parses an X.509 attribute certificate + */ +static bool parse_certificate(chunk_t blob, private_x509ac_t *this) +{ + asn1_ctx_t ctx; + bool critical; + chunk_t object; + u_int level; + u_int type = OID_UNKNOWN; + u_int extn_oid = OID_UNKNOWN; + int objectID = 0; + + asn1_init(&ctx, blob, 0, FALSE, FALSE); + while (objectID < AC_OBJ_ROOF) + { + if (!extract_object(acObjects, &objectID, &object, &level, &ctx)) + { + return FALSE; + } + + /* those objects which will parsed further need the next higher level */ + level++; + + switch (objectID) + { + case AC_OBJ_CERTIFICATE: + this->certificate = object; + break; + case AC_OBJ_CERTIFICATE_INFO: + this->certificateInfo = object; + break; + case AC_OBJ_VERSION: + this->version = (object.len) ? (1 + (u_int)*object.ptr) : 1; + DBG2(" v%d", this->version); + if (this->version != 2) + { + DBG1("v%d attribute certificates are not supported", this->version); + return FALSE; + } + break; + case AC_OBJ_HOLDER_ISSUER: + if (!parse_directoryName(object, level, FALSE, &this->holderIssuer)) + { + return FALSE; + } + break; + case AC_OBJ_HOLDER_SERIAL: + this->holderSerial = object; + break; + case AC_OBJ_ENTITY_NAME: + if (!parse_directoryName(object, level, TRUE, &this->entityName)) + { + return FALSE; + } + break; + case AC_OBJ_ISSUER_NAME: + if (!parse_directoryName(object, level, FALSE, &this->issuerName)) + { + return FALSE; + } + break; + case AC_OBJ_SIG_ALG: + this->sigAlg = parse_algorithmIdentifier(object, level, NULL); + break; + case AC_OBJ_SERIAL_NUMBER: + this->serialNumber = object; + break; + case AC_OBJ_NOT_BEFORE: + this->notBefore = asn1totime(&object, ASN1_GENERALIZEDTIME); + break; + case AC_OBJ_NOT_AFTER: + this->notAfter = asn1totime(&object, ASN1_GENERALIZEDTIME); + break; + case AC_OBJ_ATTRIBUTE_TYPE: + type = known_oid(object); + break; + case AC_OBJ_ATTRIBUTE_VALUE: + { + switch (type) + { + case OID_AUTHENTICATION_INFO: + DBG2(" need to parse authenticationInfo"); + break; + case OID_ACCESS_IDENTITY: + DBG2(" need to parse accessIdentity"); + break; + case OID_CHARGING_IDENTITY: + parse_ietfAttrSyntax(object, level, this->charging); + break; + case OID_GROUP: + parse_ietfAttrSyntax(object, level, this->groups); + break; + case OID_ROLE: + parse_roleSyntax(object, level); + break; + default: + break; + } + } + break; + case AC_OBJ_EXTN_ID: + extn_oid = known_oid(object); + break; + case AC_OBJ_CRITICAL: + critical = object.len && *object.ptr; + DBG2(" %s",(critical)?"TRUE":"FALSE"); + break; + case AC_OBJ_EXTN_VALUE: + { + switch (extn_oid) + { + case OID_CRL_DISTRIBUTION_POINTS: + DBG2(" need to parse crlDistributionPoints"); + break; + case OID_AUTHORITY_KEY_ID: + parse_authorityKeyIdentifier(object, level, + &this->authKeyID, &this->authKeySerialNumber); + break; + case OID_TARGET_INFORMATION: + DBG2(" need to parse targetInformation"); + break; + case OID_NO_REV_AVAIL: + this->noRevAvail = TRUE; + break; + default: + break; + } + } + break; + case AC_OBJ_ALGORITHM: + this->algorithm = parse_algorithmIdentifier(object, level, NULL); + break; + case AC_OBJ_SIGNATURE: + this->signature = object; + break; + default: + break; + } + objectID++; + } + this->installed = time(NULL); + return FALSE; +} + +/** + * Implements x509ac_t.destroy + */ +static void destroy(private_x509ac_t *this) +{ + DESTROY_IF(this->holderIssuer); + DESTROY_IF(this->entityName); + DESTROY_IF(this->issuerName); + this->charging->destroy_offset(this->charging, + offsetof(ietfAttr_t, destroy)); + this->groups->destroy_offset(this->groups, + offsetof(ietfAttr_t, destroy)); + free(this->certificate.ptr); + free(this); +} + +/** + * Described in header. + */ +x509ac_t *x509ac_create_from_chunk(chunk_t chunk) +{ + private_x509ac_t *this = malloc_thing(private_x509ac_t); + + /* initialize */ + this->holderIssuer = NULL; + this->entityName = NULL; + this->issuerName = NULL; + this->charging = linked_list_create(); + this->groups = linked_list_create(); + + /* public functions */ + this->public.is_valid = (err_t (*) (const x509ac_t*,time_t*))is_valid; + this->public.destroy = (void (*) (x509ac_t*))destroy; + + if (!parse_certificate(chunk, this)) + { + destroy(this); + return NULL; + } + return &this->public; +} + +/** + * Described in header. + */ +x509ac_t *x509ac_create_from_file(const char *filename) +{ + bool pgp = FALSE; + chunk_t chunk = chunk_empty; + + if (!pem_asn1_load_file(filename, NULL, "attribute certificate", &chunk, &pgp)) + { + return NULL; + } + return x509ac_create_from_chunk(chunk); +} + diff --git a/src/libstrongswan/crypto/ac.h b/src/libstrongswan/crypto/ac.h new file mode 100644 index 000000000..b7fd26c94 --- /dev/null +++ b/src/libstrongswan/crypto/ac.h @@ -0,0 +1,81 @@ +/** + * @file ac.h + * + * @brief Interface of x509ac_t. + * + */ + +/* + * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler + * Copyright (C) 2003 Martin Berner, Lukas Suter + * Copyright (C) 2007 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 . + * + * 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. + */ + +#ifndef AC_H_ +#define AC_H_ + +typedef struct x509ac_t x509ac_t; + +/** + * @brief X.509 attribute certificate. + * + * @b Constructors: + * - x509ac_create_from_chunk() + * - x509ac_create_from_file() + * + * @ingroup crypto + */ +struct x509ac_t { + + /** + * @brief Checks the validity interval of the attribute certificate + * + * @param this certificate being examined + * @param until until = min(until, notAfter) + * @return NULL if the certificate is valid + */ + err_t (*is_valid) (const x509ac_t *this, time_t *until); + + /** + * @brief Destroys the attribute certificate. + * + * @param this certificate to destroy + */ + void (*destroy) (x509ac_t *this); +}; + +/** + * @brief Read a x509 attribute certificate from a DER encoded blob. + * + * @param chunk chunk containing DER encoded data + * @return created x509ac_t certificate, or NULL if invalid. + * + * @ingroup crypto + */ +x509ac_t *x509ac_create_from_chunk(chunk_t chunk); + +/** + * @brief Read a x509 attribute certificate from a DER encoded file. + * + * @param filename file containing DER encoded data + * @return created x509ac_t certificate, or NULL if invalid. + * + * @ingroup crypto + */ +x509ac_t *x509ac_create_from_file(const char *filename); + + +#endif /* AC_H_ */ + diff --git a/src/libstrongswan/crypto/ca.c b/src/libstrongswan/crypto/ca.c index 1f566a098..07413e805 100644 --- a/src/libstrongswan/crypto/ca.c +++ b/src/libstrongswan/crypto/ca.c @@ -29,6 +29,7 @@ #include "x509.h" #include "crl.h" #include "ca.h" +#include "ac.h" #include "certinfo.h" #include "ocsp.h" @@ -64,6 +65,11 @@ struct private_ca_info_t { */ x509_t *cacert; + /** + * List of attribute certificates + */ + linked_list_t *attrcerts; + /** * List of crl URIs */ @@ -94,6 +100,7 @@ struct private_ca_info_t { /** * static options set by ca_info_set_options() */ +static strict_t strict_crl_policy = STRICT_NO; static bool cache_crls = FALSE; static u_int crl_check_interval = 0; @@ -150,6 +157,31 @@ static bool is_crl_issuer(private_ca_info_t *this, const crl_t *crl) return crl->is_issuer(crl, this->cacert); } +/** + * Implements ca_info_t.is_ca + */ +static bool is_ca(private_ca_info_t *this) +{ + return this->cacert->is_ca(this->cacert); +} + +/** + * Implements ca_info_t.is_strict + */ +static bool is_strict(private_ca_info_t *this) +{ + bool strict = strict_crl_policy != STRICT_NO; + + if (strict_crl_policy == STRICT_IFURI) + { + pthread_mutex_lock(&(this->mutex)); + strict = this->crluris->get_count(this->crluris) > 0 || + this->ocspuris->get_count(this->ocspuris) > 0; + pthread_mutex_unlock(&(this->mutex)); + } + return strict; +} + /** * Implements ca_info_t.has_crl */ @@ -213,11 +245,9 @@ static void add_crl(private_ca_info_t *this, crl_t *crl) */ static void list_crl(private_ca_info_t *this, FILE *out, bool utc) { - pthread_mutex_lock(&(this->mutex)); - - fprintf(out, "%#U\n", this->crl, utc); - - pthread_mutex_unlock(&(this->mutex)); + pthread_mutex_lock(&this->mutex); + this->crl->list(this->crl, out, utc); + pthread_mutex_unlock(&this->mutex); } /** @@ -225,26 +255,42 @@ static void list_crl(private_ca_info_t *this, FILE *out, bool utc) */ static void list_certinfos(private_ca_info_t *this, FILE *out, bool utc) { - pthread_mutex_lock(&(this->mutex)); + iterator_t *iterator; + certinfo_t *certinfo; + chunk_t authkey; + pthread_mutex_lock(&this->mutex); + + authkey = this->cacert->get_subjectKeyID(this->cacert); fprintf(out," authname: '%D'\n", this->cacert->get_subject(this->cacert)); - { - chunk_t authkey = this->cacert->get_subjectKeyID(this->cacert); + fprintf(out," authkey: %#B\n", &authkey); - fprintf(out," authkey: %#B\n", &authkey); - } + iterator = this->certinfos->create_iterator(this->certinfos, TRUE); + while (iterator->iterate(iterator, (void**)&certinfo)) { - iterator_t *iterator = this->certinfos->create_iterator(this->certinfos, TRUE); - certinfo_t *certinfo; - - while (iterator->iterate(iterator, (void**)&certinfo)) + time_t nextUpdate, thisUpdate, now; + chunk_t serial; + + now = time(NULL); + nextUpdate = certinfo->get_nextUpdate(certinfo); + thisUpdate = certinfo->get_thisUpdate(certinfo); + serial = certinfo->get_serialNumber(certinfo); + + fprintf(out, "%#T, until %#T, ", &thisUpdate, utc, &nextUpdate, utc); + if (now > nextUpdate) { - fprintf(out, "%#Y\n", certinfo, utc); + fprintf(out, "expired (%V ago)\n", &now, &nextUpdate); } - iterator->destroy(iterator); + else + { + fprintf(out, "ok (expires in %V)\n", &now, &nextUpdate); + } + fprintf(out, " serial: %#B, %N\n", &serial, + cert_status_names, certinfo->get_status(certinfo)); } + iterator->destroy(iterator); - pthread_mutex_unlock(&(this->mutex)); + pthread_mutex_unlock(&this->mutex); } /** @@ -644,6 +690,8 @@ static void purge_ocsp(private_ca_info_t *this) */ static void destroy(private_ca_info_t *this) { + this->attrcerts->destroy_offset(this->attrcerts, + offsetof(x509ac_t, destroy)); this->crluris->destroy_offset(this->crluris, offsetof(identification_t, destroy)); this->ocspuris->destroy_offset(this->ocspuris, @@ -656,92 +704,59 @@ static void destroy(private_ca_info_t *this) } /** - * output handler in printf() + * list the info of this CA */ -static int print(FILE *stream, const struct printf_info *info, - const void *const *args) +static void list(private_ca_info_t* this, FILE* out, bool utc) { - private_ca_info_t *this = *((private_ca_info_t**)(args[0])); - bool utc = TRUE; - int written = 0; - const x509_t *cacert; + chunk_t chunk; + identification_t *uri; + iterator_t *iterator; + bool first; - if (info->alt) - { - utc = *((bool*)args[1]); - } - if (this == NULL) - { - return fprintf(stream, "(null)"); - } - pthread_mutex_lock(&(this->mutex)); - written += fprintf(stream, "%#T", &this->installed, utc); + fprintf(out, "%#T", &this->installed, utc); if (this->name) { - written += fprintf(stream, ", \"%s\"\n", this->name); + fprintf(out, ", \"%s\"\n", this->name); } else { - written += fprintf(stream, "\n"); + fprintf(out, "\n"); } - cacert = this->cacert; - written += fprintf(stream, " authname: '%D'\n", cacert->get_subject(cacert)); - { - chunk_t authkey = cacert->get_subjectKeyID(cacert); - - written += fprintf(stream, " authkey: %#B\n", &authkey); - } + fprintf(out, " authname: '%D'\n", this->cacert->get_subject(this->cacert)); + chunk = this->cacert->get_subjectKeyID(this->cacert); + fprintf(out, " authkey: %#B\n", &chunk); + chunk = this->cacert->get_keyid(this->cacert); + fprintf(out, " keyid: %#B\n", &chunk); + + first = TRUE; + iterator = this->crluris->create_iterator(this->crluris, TRUE); + while (iterator->iterate(iterator, (void**)&uri)) { - chunk_t keyid = cacert->get_keyid(cacert); - - written += fprintf(stream, " keyid: %#B\n", &keyid); - } - { - identification_t *crluri; - iterator_t *iterator = this->crluris->create_iterator(this->crluris, TRUE); - bool first = TRUE; - - while (iterator->iterate(iterator, (void**)&crluri)) - { - written += fprintf(stream, " %s '%D'\n", - first? "crluris:":" ", crluri); - first = FALSE; - } - iterator->destroy(iterator); + fprintf(out, " %s '%D'\n", first ? "crluris:":" ", uri); + first = FALSE; } + iterator->destroy(iterator); + + first = TRUE; + iterator = this->ocspuris->create_iterator(this->ocspuris, TRUE); + while (iterator->iterate(iterator, (void**)&uri)) { - identification_t *ocspuri; - iterator_t *iterator = this->ocspuris->create_iterator(this->ocspuris, TRUE); - bool first = TRUE; - - while (iterator->iterate(iterator, (void**)&ocspuri)) - { - written += fprintf(stream, " %s '%D'\n", - first? "ocspuris:":" ", ocspuri); - first = FALSE; - } - iterator->destroy(iterator); + fprintf(out, " %s '%D'\n", first ? "ocspuris:":" ", uri); + first = FALSE; } + iterator->destroy(iterator); pthread_mutex_unlock(&(this->mutex)); - return written; -} - -/** - * register printf() handlers - */ -static void __attribute__ ((constructor))print_register() -{ - register_printf_function(PRINTF_CAINFO, print, arginfo_ptr_alt_ptr_int); } /* * Described in header. */ -void ca_info_set_options(bool cache, u_int interval) +void ca_info_set_options(strict_t strict, bool cache, u_int interval) { + strict_crl_policy = strict; cache_crls = cache; crl_check_interval = interval; } @@ -757,6 +772,7 @@ ca_info_t *ca_info_create(const char *name, x509_t *cacert) this->installed = time(NULL); this->name = (name == NULL)? NULL:strdup(name); this->cacert = cacert; + this->attrcerts = linked_list_create(); this->crluris = linked_list_create(); this->ocspuris = linked_list_create(); this->certinfos = linked_list_create(); @@ -770,10 +786,13 @@ ca_info_t *ca_info_create(const char *name, x509_t *cacert) this->public.equals_name_release_info = (bool (*) (ca_info_t*,const char*))equals_name_release_info; this->public.is_cert_issuer = (bool (*) (ca_info_t*,const x509_t*))is_cert_issuer; this->public.is_crl_issuer = (bool (*) (ca_info_t*,const crl_t*))is_crl_issuer; + this->public.is_ca = (bool (*) (ca_info_t*))is_ca; + this->public.is_strict = (bool (*) (ca_info_t*))is_strict; this->public.add_info = (void (*) (ca_info_t*,const ca_info_t*))add_info; this->public.add_crl = (void (*) (ca_info_t*,crl_t*))add_crl; this->public.has_crl = (bool (*) (ca_info_t*))has_crl; this->public.has_certinfos = (bool (*) (ca_info_t*))has_certinfos; + this->public.list = (void (*) (ca_info_t*,FILE*,bool))list; this->public.list_crl = (void (*) (ca_info_t*,FILE*,bool))list_crl; this->public.list_certinfos = (void (*) (ca_info_t*,FILE*,bool))list_certinfos; this->public.add_crluri = (void (*) (ca_info_t*,chunk_t))add_crluri; diff --git a/src/libstrongswan/crypto/ca.h b/src/libstrongswan/crypto/ca.h index c494a4468..ff6271b15 100644 --- a/src/libstrongswan/crypto/ca.h +++ b/src/libstrongswan/crypto/ca.h @@ -26,13 +26,15 @@ typedef struct ca_info_t ca_info_t; #include -#include - -#include #include "x509.h" #include "crl.h" +#define MAX_CA_PATH_LEN 7 + +/*forward declaration */ +struct credential_store_t; + /** * @brief X.509 certification authority information record * @@ -80,6 +82,22 @@ struct ca_info_t { */ bool (*is_crl_issuer) (ca_info_t *this, const crl_t *crl); + /** + * @brief Checks if the ca certificate has the isCA flag set + * + * @param this ca info object + * @return TRUE if the isCA flag is set + */ + bool (*is_ca) (ca_info_t *this); + + /** + * @brief Checks if the ca enforces a strict crl policy + * + * @param this ca info object + * @return TRUE if the crl policy is strict + */ + bool (*is_strict) (ca_info_t *this); + /** * @brief Merges info from a secondary ca info object * @@ -112,6 +130,16 @@ struct ca_info_t { */ bool (*has_certinfos) (ca_info_t *this); + /** + * @brief Print the CA info onto the console + * + * @param this ca info object + * @param out output stream + * @param utc TRUE - utc + FALSE - local time + */ + void (*list) (ca_info_t *this, FILE *out, bool utc); + /** * @brief List the CRL onto the console * @@ -174,7 +202,7 @@ struct ca_info_t { * @param credentials credential store needed for trust path verification * @return certificate status */ - cert_status_t (*verify_by_ocsp) (ca_info_t* this, certinfo_t* certinfo, credential_store_t* credentials); + cert_status_t (*verify_by_ocsp) (ca_info_t* this, certinfo_t* certinfo, struct credential_store_t* credentials); /** * @brief Purge the OCSP certinfos of a ca info record @@ -199,7 +227,7 @@ struct ca_info_t { * * @ingroup crypto */ -void ca_info_set_options(bool cache, u_int interval); +void ca_info_set_options(strict_t strict, bool cache, u_int interval); /** * @brief Create a ca info record diff --git a/src/libstrongswan/crypto/certinfo.c b/src/libstrongswan/crypto/certinfo.c index 654e4c2bd..8a125e247 100644 --- a/src/libstrongswan/crypto/certinfo.c +++ b/src/libstrongswan/crypto/certinfo.c @@ -221,54 +221,6 @@ static void destroy(private_certinfo_t *this) free(this); } -/** - * output handler in printf() - */ -static int print(FILE *stream, const struct printf_info *info, - const void *const *args) -{ - private_certinfo_t *this = *((private_certinfo_t**)(args[0])); - bool utc = TRUE; - int written = 0; - time_t now; - - if (info->alt) - { - utc = *((bool*)args[1]); - } - - if (this == NULL) - { - return fprintf(stream, "(null)"); - } - - now = time(NULL); - - written += fprintf(stream, "%#T, until %#T, ", - &this->thisUpdate, utc, - &this->nextUpdate, utc); - if (now > this->nextUpdate) - { - written += fprintf(stream, "expired (%V ago)\n", &now, &this->nextUpdate); - } - else - { - written += fprintf(stream, "ok (expires in %V)\n", &now, &this->nextUpdate); - } - written += fprintf(stream, " serial: %#B, %N", - &this->serialNumber, - cert_status_names, this->status); - return written; -} - -/** - * register printf() handlers - */ -static void __attribute__ ((constructor))print_register() -{ - register_printf_function(PRINTF_CERTINFO, print, arginfo_ptr_alt_ptr_int); -} - /* * Described in header. */ diff --git a/src/libstrongswan/crypto/crl.c b/src/libstrongswan/crypto/crl.c index 00d6a3ac3..b4ae37b2e 100755 --- a/src/libstrongswan/crypto/crl.c +++ b/src/libstrongswan/crypto/crl.c @@ -39,10 +39,6 @@ #define CRL_WARNING_INTERVAL 7 /* days */ -extern char* check_expiry(time_t expiration_date, int warning_interval, bool strict); -extern time_t parse_time(chunk_t blob, int level0); -extern void parse_authorityKeyIdentifier(chunk_t blob, int level0 , chunk_t *authKeyID, chunk_t *authKeySerialNumber); - /* access structure for a revoked certificate */ typedef struct revokedCert_t revokedCert_t; @@ -99,6 +95,11 @@ struct private_crl_t { */ identification_t *issuer; + /** + * CRL number + */ + chunk_t crlNumber; + /** * Time when the crl was generated */ @@ -291,6 +292,14 @@ bool parse_x509crl(chunk_t blob, u_int level0, private_crl_t *crl) { parse_authorityKeyIdentifier(object, level, &crl->authKeyID, &crl->authKeySerialNumber); } + else if (extn_oid == OID_CRL_NUMBER) + { + if (!parse_asn1_simple_object(&object, ASN1_INTEGER, level, "crlNumber")) + { + return FALSE; + } + crl->crlNumber = object; + } } break; case CRL_OBJ_ALGORITHM: @@ -416,66 +425,47 @@ static void destroy(private_crl_t *this) } /** - * output handler in printf() + * Implementation of crl_t.list. */ -static int print(FILE *stream, const struct printf_info *info, - const void *const *args) +static void list(private_crl_t *this, FILE* out, bool utc) { - private_crl_t *this = *((private_crl_t**)(args[0])); - bool utc = TRUE; - int written = 0; time_t now; - if (info->alt) - { - utc = *((bool*)args[1]); - } - - if (this == NULL) - { - return fprintf(stream, "(null)"); - } - now = time(NULL); - written += fprintf(stream, "%#T, revoked certs: %d\n", &this->installed, utc, + fprintf(out, "%#T, revoked certs: %d\n", &this->installed, utc, this->revokedCertificates->get_count(this->revokedCertificates)); - written += fprintf(stream, " issuer: '%D'\n", this->issuer); - written += fprintf(stream, " updates: this %#T\n", &this->thisUpdate, utc); - written += fprintf(stream, " next %#T ", &this->nextUpdate, utc); + fprintf(out, " issuer: '%D'\n", this->issuer); + if (this->crlNumber.ptr) + { + fprintf(out, " crlnumber: %#B\n", &this->crlNumber); + } + fprintf(out, " updates: this %#T\n", &this->thisUpdate, utc); + fprintf(out, " next %#T ", &this->nextUpdate, utc); if (this->nextUpdate == UNDEFINED_TIME) { - written += fprintf(stream, "ok (expires never)"); + fprintf(out, "ok (expires never)\n"); } else if (now > this->nextUpdate) { - written += fprintf(stream, "expired (%V ago)", &now, &this->nextUpdate); + fprintf(out, "expired (%V ago)\n", &now, &this->nextUpdate); } else if (now > this->nextUpdate - CRL_WARNING_INTERVAL * 60 * 60 * 24) { - written += fprintf(stream, "ok (expires in %V)", &now, &this->nextUpdate); + fprintf(out, "ok (expires in %V)\n", &now, &this->nextUpdate); } else { - written += fprintf(stream, "ok"); + fprintf(out, "ok\n"); } if (this->authKeyID.ptr) { - written += fprintf(stream, "\n authkey: %#B", &this->authKeyID); + fprintf(out, " authkey: %#B\n", &this->authKeyID); } if (this->authKeySerialNumber.ptr) { - written += fprintf(stream, "\n aserial: %#B", &this->authKeySerialNumber); + fprintf(out, " aserial: %#B\n", &this->authKeySerialNumber); } - return written; -} - -/** - * register printf() handlers - */ -static void __attribute__ ((constructor))print_register() -{ - register_printf_function(PRINTF_CRL, print, arginfo_ptr_alt_ptr_int); } /* @@ -489,6 +479,7 @@ crl_t *crl_create_from_chunk(chunk_t chunk) this->crlDistributionPoints = linked_list_create(); this->tbsCertList = chunk_empty; this->issuer = NULL; + this->crlNumber = chunk_empty; this->revokedCertificates = linked_list_create(); this->authKeyID = chunk_empty; this->authKeySerialNumber = chunk_empty; @@ -502,6 +493,7 @@ crl_t *crl_create_from_chunk(chunk_t chunk) this->public.verify = (bool (*) (const crl_t*,const rsa_public_key_t*))verify; this->public.get_status = (void (*) (const crl_t*,certinfo_t*))get_status; this->public.write_to_file = (bool (*) (const crl_t*,const char*,mode_t,bool))write_to_file; + this->public.list = (void(*)(crl_t*, FILE* out, bool utc))list; this->public.destroy = (void (*) (crl_t*))destroy; if (!parse_x509crl(chunk, 0, this)) @@ -520,14 +512,10 @@ crl_t *crl_create_from_file(const char *filename) { bool pgp = FALSE; chunk_t chunk = chunk_empty; - crl_t *crl = NULL; if (!pem_asn1_load_file(filename, NULL, "crl", &chunk, &pgp)) + { return NULL; - - crl = crl_create_from_chunk(chunk); - - if (crl == NULL) - free(chunk.ptr); - return crl; + } + return crl_create_from_chunk(chunk); } diff --git a/src/libstrongswan/crypto/crl.h b/src/libstrongswan/crypto/crl.h index 8a11fc390..a367c3aff 100755 --- a/src/libstrongswan/crypto/crl.h +++ b/src/libstrongswan/crypto/crl.h @@ -104,6 +104,15 @@ struct crl_t { * @param certinfo certinfo is updated */ void (*get_status) (const crl_t *this, certinfo_t *certinfo); + + /** + * @brief Log the info of this CRL to out. + * + * @param this calling object + * @param out stream to write to + * @param utc TRUE for UTC, FALSE for local time + */ + void (*list)(crl_t *this, FILE* out, bool utc); /** * @brief Write a der-encoded crl to a file diff --git a/src/libstrongswan/crypto/ocsp.c b/src/libstrongswan/crypto/ocsp.c index 471996c8e..0d8093e4a 100644 --- a/src/libstrongswan/crypto/ocsp.c +++ b/src/libstrongswan/crypto/ocsp.c @@ -770,7 +770,7 @@ static void ocsp_process_response(private_ocsp_t *this, response_t *res, credent if (res->responder_cert->is_ocsp_signer(res->responder_cert)) { DBG2("received certificate is ocsp signer"); - if (credentials->is_trusted(credentials, res->responder_cert)) + if (credentials->is_trusted(credentials, "OCSP signing", res->responder_cert)) { DBG1("received ocsp signer certificate is trusted"); ocsp_cert = credentials->add_auth_certificate(credentials, diff --git a/src/libstrongswan/crypto/x509.c b/src/libstrongswan/crypto/x509.c index 58fcff16d..5bf3f26d7 100755 --- a/src/libstrongswan/crypto/x509.c +++ b/src/libstrongswan/crypto/x509.c @@ -6,7 +6,12 @@ */ /* - * Copyright (C) 2006 Martin Willi + * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann + * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss + * Copyright (C) 2002 Mario Strasser + * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur + * Copyright (C) 2006 Martin Willi, Andreas Steffen + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -116,6 +121,11 @@ struct private_x509_t { */ identification_t *issuer; + /** + * link to the info recored of the certificate issuer + */ + ca_info_t *ca_info; + /** * Start time of certificate validity */ @@ -171,6 +181,11 @@ struct private_x509_t { */ chunk_t authKeySerialNumber; + /** + * Indicates if the certificate is self-signed + */ + bool isSelfSigned; + /** * CA basic constraints flag */ @@ -249,19 +264,6 @@ static const asn1Object_t basicConstraintsObjects[] = { #define BASIC_CONSTRAINTS_CA 1 #define BASIC_CONSTRAINTS_ROOF 4 -/** - * ASN.1 definition of time - */ -static const asn1Object_t timeObjects[] = { - { 0, "utcTime", ASN1_UTCTIME, ASN1_OPT|ASN1_BODY }, /* 0 */ - { 0, "end opt", ASN1_EOC, ASN1_END }, /* 1 */ - { 0, "generalizeTime",ASN1_GENERALIZEDTIME, ASN1_OPT|ASN1_BODY }, /* 2 */ - { 0, "end opt", ASN1_EOC, ASN1_END } /* 3 */ -}; -#define TIME_UTC 0 -#define TIME_GENERALIZED 2 -#define TIME_ROOF 4 - /** * ASN.1 definition of a keyIdentifier */ @@ -545,7 +547,7 @@ static identification_t *parse_generalName(chunk_t blob, int level0) /** * extracts one or several GNs and puts them into a chained list */ -static void parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list) +void parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list) { asn1_ctx_t ctx; chunk_t object; @@ -571,33 +573,6 @@ static void parse_generalNames(chunk_t blob, int level0, bool implicit, linked_l return; } -/** - * extracts and converts a UTCTIME or GENERALIZEDTIME object - */ -time_t parse_time(chunk_t blob, int level0) -{ - asn1_ctx_t ctx; - chunk_t object; - u_int level; - int objectID = 0; - - asn1_init(&ctx, blob, level0, FALSE, FALSE); - - while (objectID < TIME_ROOF) - { - if (!extract_object(timeObjects, &objectID, &object, &level, &ctx)) - return 0; - - if (objectID == TIME_UTC || objectID == TIME_GENERALIZED) - { - return asn1totime(&object, (objectID == TIME_UTC) - ? ASN1_UTCTIME : ASN1_GENERALIZEDTIME); - } - objectID++; - } - return 0; -} - /** * extracts a keyIdentifier */ @@ -624,7 +599,11 @@ void parse_authorityKeyIdentifier(chunk_t blob, int level0 , chunk_t *authKeyID, u_int level; int objectID = 0; + *authKeyID = chunk_empty; + *authKeySerialNumber = chunk_empty; + asn1_init(&ctx, blob, level0, FALSE, FALSE); + while (objectID < AUTH_KEY_ID_ROOF) { if (!extract_object(authorityKeyIdentifierObjects, &objectID, &object, &level, &ctx)) @@ -763,7 +742,7 @@ static void parse_crlDistributionPoints(chunk_t blob, int level0, linked_list_t /** * Parses an X.509v3 certificate */ -static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *cert) +static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *this) { asn1_ctx_t ctx; bool critical; @@ -779,38 +758,41 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *cert) { return FALSE; } + /* those objects which will parsed further need the next higher level */ level++; - switch (objectID) { + + switch (objectID) + { case X509_OBJ_CERTIFICATE: - cert->certificate = object; + this->certificate = object; break; case X509_OBJ_TBS_CERTIFICATE: - cert->tbsCertificate = object; + this->tbsCertificate = object; break; case X509_OBJ_VERSION: - cert->version = (object.len) ? (1+(u_int)*object.ptr) : 1; - DBG2(" v%d", cert->version); + this->version = (object.len) ? (1+(u_int)*object.ptr) : 1; + DBG2(" v%d", this->version); break; case X509_OBJ_SERIAL_NUMBER: - cert->serialNumber = object; + this->serialNumber = object; break; case X509_OBJ_SIG_ALG: - cert->sigAlg = parse_algorithmIdentifier(object, level, NULL); + this->sigAlg = parse_algorithmIdentifier(object, level, NULL); break; case X509_OBJ_ISSUER: - cert->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object); - DBG2(" '%D'", cert->issuer); + this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object); + DBG2(" '%D'", this->issuer); break; case X509_OBJ_NOT_BEFORE: - cert->notBefore = parse_time(object, level); + this->notBefore = parse_time(object, level); break; case X509_OBJ_NOT_AFTER: - cert->notAfter = parse_time(object, level); + this->notAfter = parse_time(object, level); break; case X509_OBJ_SUBJECT: - cert->subject = identification_create_from_encoding(ID_DER_ASN1_DN, object); - DBG2(" '%D'", cert->subject); + this->subject = identification_create_from_encoding(ID_DER_ASN1_DN, object); + DBG2(" '%D'", this->subject); break; case X509_OBJ_SUBJECT_PUBLIC_KEY_ALGORITHM: if (parse_algorithmIdentifier(object, level, NULL) != OID_RSA_ENCRYPTION) @@ -832,7 +814,7 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *cert) } break; case X509_OBJ_RSA_PUBLIC_KEY: - cert->subjectPublicKey = object; + this->subjectPublicKey = object; break; case X509_OBJ_EXTN_ID: extn_oid = known_oid(object); @@ -843,27 +825,28 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *cert) break; case X509_OBJ_EXTN_VALUE: { - switch (extn_oid) { + switch (extn_oid) + { case OID_SUBJECT_KEY_ID: - cert->subjectKeyID = chunk_clone(parse_keyIdentifier(object, level, FALSE)); + this->subjectKeyID = chunk_clone(parse_keyIdentifier(object, level, FALSE)); break; case OID_SUBJECT_ALT_NAME: - parse_generalNames(object, level, FALSE, cert->subjectAltNames); + parse_generalNames(object, level, FALSE, this->subjectAltNames); break; case OID_BASIC_CONSTRAINTS: - cert->isCA = parse_basicConstraints(object, level); + this->isCA = parse_basicConstraints(object, level); break; case OID_CRL_DISTRIBUTION_POINTS: - parse_crlDistributionPoints(object, level, cert->crlDistributionPoints); + parse_crlDistributionPoints(object, level, this->crlDistributionPoints); break; case OID_AUTHORITY_KEY_ID: - parse_authorityKeyIdentifier(object, level , &cert->authKeyID, &cert->authKeySerialNumber); + parse_authorityKeyIdentifier(object, level , &this->authKeyID, &this->authKeySerialNumber); break; case OID_AUTHORITY_INFO_ACCESS: - parse_authorityInfoAccess(object, level, cert->ocspAccessLocations); + parse_authorityInfoAccess(object, level, this->ocspAccessLocations); break; case OID_EXTENDED_KEY_USAGE: - cert->isOcspSigner = parse_extendedKeyUsage(object, level); + this->isOcspSigner = parse_extendedKeyUsage(object, level); break; case OID_NS_REVOCATION_URL: case OID_NS_CA_REVOCATION_URL: @@ -878,10 +861,10 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *cert) break; } case X509_OBJ_ALGORITHM: - cert->algorithm = parse_algorithmIdentifier(object, level, NULL); + this->algorithm = parse_algorithmIdentifier(object, level, NULL); break; case X509_OBJ_SIGNATURE: - cert->signature = object; + this->signature = object; break; default: break; @@ -889,15 +872,16 @@ static bool parse_certificate(chunk_t blob, u_int level0, private_x509_t *cert) objectID++; } - if (cert->subjectKeyID.ptr == NULL) + /* generate the subjectKeyID if it is missing in the certificate */ + if (this->subjectKeyID.ptr == NULL) { hasher_t *hasher = hasher_create(HASH_SHA1); - hasher->allocate_hash(hasher, cert->subjectPublicKey, &cert->subjectKeyID); + hasher->allocate_hash(hasher, this->subjectPublicKey, &this->subjectKeyID); hasher->destroy(hasher); } - time(&cert->installed); + this->installed = time(NULL); return TRUE; } @@ -950,7 +934,7 @@ static bool is_ocsp_signer(const private_x509_t *this) */ static bool is_self_signed(const private_x509_t *this) { - return this->subject->equals(this->subject, this->issuer); + return this->isSelfSigned; } /** @@ -1042,6 +1026,22 @@ static identification_t *get_subject(const private_x509_t *this) return this->subject; } +/** + * Implements x509_t.set_ca_info + */ +static void set_ca_info(private_x509_t *this, ca_info_t *ca_info) +{ + this->ca_info = ca_info; +} + +/** + * Implements x509_t.get_ca_info + */ +static ca_info_t *get_ca_info(const private_x509_t *this) +{ + return this->ca_info; +} + /** * Implements x509_t.set_until */ @@ -1121,39 +1121,23 @@ static bool verify(const private_x509_t *this, const rsa_public_key_t *signer) { return signer->verify_emsa_pkcs1_signature(signer, this->tbsCertificate, this->signature) == SUCCESS; } - + /** - * output handler in printf() + * Implementation of x509_t.list. */ -static int print(FILE *stream, const struct printf_info *info, - const void *const *args) +static void list(private_x509_t *this, FILE *out, bool utc) { - private_x509_t *this = *((private_x509_t**)(args[0])); iterator_t *iterator; - bool utc = TRUE; - int written = 0; - - if (info->alt) - { - utc = *((bool*)(args[1])); - } - - if (this == NULL) - { - return fprintf(stream, "(null)"); - } - - /* determine the current time */ time_t now = time(NULL); - written += fprintf(stream, "%#T\n", &this->installed, utc); + fprintf(out, "%#T\n", &this->installed, utc); if (this->subjectAltNames->get_count(this->subjectAltNames)) { identification_t *subjectAltName; bool first = TRUE; - written += fprintf(stream, " altNames: "); + fprintf(out, " altNames: "); iterator = this->subjectAltNames->create_iterator(this->subjectAltNames, TRUE); while (iterator->iterate(iterator, (void**)&subjectAltName)) { @@ -1163,71 +1147,71 @@ static int print(FILE *stream, const struct printf_info *info, } else { - written += fprintf(stream, ", "); + fprintf(out, ", "); } - written += fprintf(stream, "'%D'", subjectAltName); + fprintf(out, "'%D'", subjectAltName); } iterator->destroy(iterator); - written += fprintf(stream, "\n"); + fprintf(out, "\n"); } - written += fprintf(stream, " subject: '%D'\n", this->subject); - written += fprintf(stream, " issuer: '%D'\n", this->issuer); - written += fprintf(stream, " serial: %#B\n", &this->serialNumber); - written += fprintf(stream, " validity: not before %#T, ", &this->notBefore, utc); + fprintf(out, " subject: '%D'\n", this->subject); + fprintf(out, " issuer: '%D'\n", this->issuer); + fprintf(out, " serial: %#B\n", &this->serialNumber); + fprintf(out, " validity: not before %#T, ", &this->notBefore, utc); if (now < this->notBefore) { - written += fprintf(stream, "not valid yet (valid in %V)\n", &now, &this->notBefore); + fprintf(out, "not valid yet (valid in %V)\n", &now, &this->notBefore); } else { - written += fprintf(stream, "ok\n"); + fprintf(out, "ok\n"); } - written += fprintf(stream, " not after %#T, ", &this->notAfter, utc); + fprintf(out, " not after %#T, ", &this->notAfter, utc); if (now > this->notAfter) { - written += fprintf(stream, "expired (%V ago)\n", &now, &this->notAfter); + fprintf(out, "expired (%V ago)\n", &now, &this->notAfter); } else { - written += fprintf(stream, "ok"); + fprintf(out, "ok"); if (now > this->notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24) { - written += fprintf(stream, " (expires in %V)", &now, &this->notAfter); + fprintf(out, " (expires in %V)", &now, &this->notAfter); } - written += fprintf(stream, " \n"); + fprintf(out, " \n"); } { chunk_t keyid = this->public_key->get_keyid(this->public_key); - written += fprintf(stream, " keyid: %#B\n", &keyid); + fprintf(out, " keyid: %#B\n", &keyid); } if (this->subjectKeyID.ptr) { - written += fprintf(stream, " subjkey: %#B\n", &this->subjectKeyID); + fprintf(out, " subjkey: %#B\n", &this->subjectKeyID); } if (this->authKeyID.ptr) { - written += fprintf(stream, " authkey: %#B\n", &this->authKeyID); + fprintf(out, " authkey: %#B\n", &this->authKeyID); } if (this->authKeySerialNumber.ptr) { - written += fprintf(stream, " aserial: %#B\n", &this->authKeySerialNumber); + fprintf(out, " aserial: %#B\n", &this->authKeySerialNumber); } - written += fprintf(stream, " pubkey: RSA %d bits", BITS_PER_BYTE * - this->public_key->get_keysize(this->public_key)); - written += fprintf(stream, ", status %N", - cert_status_names, this->status); + fprintf(out, " pubkey: RSA %d bits", BITS_PER_BYTE * + this->public_key->get_keysize(this->public_key)); + fprintf(out, ", status %N", + cert_status_names, this->status); switch (this->status) { case CERT_GOOD: - written += fprintf(stream, " until %#T", &this->until, utc); + fprintf(out, " until %#T", &this->until, utc); break; case CERT_REVOKED: - written += fprintf(stream, " on %#T", &this->until, utc); + fprintf(out, " on %#T", &this->until, utc); break; case CERT_UNKNOWN: case CERT_UNDEFINED: @@ -1235,15 +1219,6 @@ static int print(FILE *stream, const struct printf_info *info, default: break; } - return written; -} - -/** - * register printf() handlers - */ -static void __attribute__ ((constructor))print_register() -{ - register_printf_function(PRINTF_X509, print, arginfo_ptr_alt_ptr_int); } /** @@ -1277,6 +1252,7 @@ x509_t *x509_create_from_chunk(chunk_t chunk, u_int level) this->public_key = NULL; this->subject = NULL; this->issuer = NULL; + this->ca_info = NULL; this->subjectAltNames = linked_list_create(); this->crlDistributionPoints = linked_list_create(); this->ocspAccessLocations = linked_list_create(); @@ -1284,6 +1260,8 @@ x509_t *x509_create_from_chunk(chunk_t chunk, u_int level) this->authKeyID = chunk_empty; this->authKeySerialNumber = chunk_empty; this->authority_flags = AUTH_NONE; + this->isCA = FALSE; + this->isOcspSigner = FALSE; /* public functions */ this->public.equals = (bool (*) (const x509_t*,const x509_t*))equals; @@ -1300,6 +1278,8 @@ x509_t *x509_create_from_chunk(chunk_t chunk, u_int level) this->public.get_keyid = (chunk_t (*) (const x509_t*))get_keyid; this->public.get_issuer = (identification_t* (*) (const x509_t*))get_issuer; this->public.get_subject = (identification_t* (*) (const x509_t*))get_subject; + this->public.set_ca_info = (void (*) (x509_t*,ca_info_t*))set_ca_info; + this->public.get_ca_info = (ca_info_t* (*) (const x509_t*))get_ca_info; this->public.set_until = (void (*) (x509_t*,time_t))set_until; this->public.get_until = (time_t (*) (const x509_t*))get_until; this->public.set_status = (void (*) (x509_t*,cert_status_t))set_status; @@ -1310,6 +1290,7 @@ x509_t *x509_create_from_chunk(chunk_t chunk, u_int level) this->public.create_crluri_iterator = (iterator_t* (*) (const x509_t*))create_crluri_iterator; this->public.create_ocspuri_iterator = (iterator_t* (*) (const x509_t*))create_ocspuri_iterator; this->public.verify = (bool (*) (const x509_t*,const rsa_public_key_t*))verify; + this->public.list = (void(*)(x509_t*, FILE *out, bool utc))list; this->public.destroy = (void (*) (x509_t*))destroy; if (!parse_certificate(chunk, level, this)) @@ -1325,9 +1306,27 @@ x509_t *x509_create_from_chunk(chunk_t chunk, u_int level) destroy(this); return NULL; } + /* set trusted lifetime of public key to notAfter */ - this->status = is_self_signed(this)? CERT_GOOD:CERT_UNDEFINED; this->until = this->notAfter; + + /* check if the certificate is self-signed */ + this->isSelfSigned = FALSE; + if (this->subject->equals(this->subject, this->issuer)) + { + this->isSelfSigned = this->public_key->verify_emsa_pkcs1_signature(this->public_key, + this->tbsCertificate, this->signature) == SUCCESS; + } + if (this->isSelfSigned) + { + DBG2(" certificate is self-signed"); + this->status = CERT_GOOD; + } + else + { + this->status = CERT_UNDEFINED; + } + return &this->public; } @@ -1338,17 +1337,13 @@ x509_t *x509_create_from_file(const char *filename, const char *label) { bool pgp = FALSE; chunk_t chunk = chunk_empty; - x509_t *cert = NULL; char cert_label[BUF_LEN]; snprintf(cert_label, BUF_LEN, "%s certificate", label); if (!pem_asn1_load_file(filename, NULL, cert_label, &chunk, &pgp)) + { return NULL; - - cert = x509_create_from_chunk(chunk, 0); - - if (cert == NULL) - free(chunk.ptr); - return cert; + } + return x509_create_from_chunk(chunk, 0); } diff --git a/src/libstrongswan/crypto/x509.h b/src/libstrongswan/crypto/x509.h index a949d99d2..c6fe148d4 100755 --- a/src/libstrongswan/crypto/x509.h +++ b/src/libstrongswan/crypto/x509.h @@ -6,7 +6,12 @@ */ /* + * Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann + * Copyright (C) 2001 Marco Bertossa, Andreas Schleiss + * Copyright (C) 2002 Mario Strasser + * Copyright (C) 2000-2004 Andreas Steffen, Zuercher Hochschule Winterthur * Copyright (C) 2006 Martin Willi, Andreas Steffen + * * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -28,8 +33,10 @@ typedef struct x509_t x509_t; #include #include #include +#include #include #include +#include /* authority flags */ @@ -44,12 +51,8 @@ typedef struct x509_t x509_t; * @b Constructors: * - x509_create_from_chunk() * - x509_create_from_file() - * - * @todo more code cleanup needed! - * @todo fix unimplemented functions... - * @todo handle memory management * - * @ingroup transforms + * @ingroup crypto */ struct x509_t { @@ -151,7 +154,7 @@ struct x509_t { chunk_t (*get_keyid) (const x509_t *this); /** - * @brief Get the certificate issuer's ID. + * @brief Get the issuerDistinguishedName * * The resulting ID is always a identification_t * of type ID_DER_ASN1_DN. @@ -162,7 +165,7 @@ struct x509_t { identification_t *(*get_issuer) (const x509_t *this); /** - * @brief Get the subjectDistinguisheName. + * @brief Get the subjectDistinguishedName. * * The resulting ID is always a identification_t * of type ID_DER_ASN1_DN. @@ -172,6 +175,26 @@ struct x509_t { */ identification_t *(*get_subject) (const x509_t *this); + /** + * @brief Set a link ca info + * + * @param this calling object + * @param ca_info link to the info record of the issuing ca + */ + void (*set_ca_info) (x509_t *this, ca_info_t *ca_info); + + /** + * @brief Get the . + * + * The resulting ID is always a identification_t + * of type ID_DER_ASN1_DN. + * + * @param this calling object + * @return link to the info record of the issuing ca + * or NULL if it does not [yet] exist + */ + ca_info_t *(*get_ca_info) (const x509_t *this); + /** * @brief Create an iterator for the crlDistributionPoints. * @@ -257,7 +280,16 @@ struct x509_t { * @return TRUE if self-signed */ bool (*is_self_signed) (const x509_t *this); - + + /** + * @brief Log the certificate info to out. + * + * @param this calling object + * @param out stream to write to + * @param utc TRUE for UTC times, FALSE for local time + */ + void (*list)(x509_t *this, FILE *out, bool utc); + /** * @brief Destroys the certificate. * @@ -272,7 +304,7 @@ struct x509_t { * @param chunk chunk containing DER encoded data * @return created x509_t certificate, or NULL if invlid. * - * @ingroup transforms + * @ingroup crypto */ x509_t *x509_create_from_chunk(chunk_t chunk, u_int level); @@ -283,8 +315,32 @@ x509_t *x509_create_from_chunk(chunk_t chunk, u_int level); * @param label label describing kind of certificate * @return created x509_t certificate, or NULL if invalid. * - * @ingroup transforms + * @ingroup crypto */ x509_t *x509_create_from_file(const char *filename, const char *label); +/** + * @brief Parses a DER encoded authorityKeyIdentifier + * + * @param blob blob containing DER encoded data + * @param level0 indicates the current parsing level + * @param authKeyID assigns the authorityKeyIdentifier + * @param authKeySerialNumber assigns the authKeySerialNumber + * + * @ingroup crypto + */ +void parse_authorityKeyIdentifier(chunk_t blob, int level0, chunk_t *authKeyID, chunk_t *authKeySerialNumber); + +/** + * @brief Parses DER encoded generalNames + * + * @param blob blob containing DER encoded data + * @param level0 indicates the current parsing level + * @param implicit implicit coding is used + * @param list linked list of decoded generalNames + * + * @ingroup crypto + */ +void parse_generalNames(chunk_t blob, int level0, bool implicit, linked_list_t *list); + #endif /* X509_H_ */ diff --git a/src/libstrongswan/library.h b/src/libstrongswan/library.h index 7c7f087f0..67a05f118 100644 --- a/src/libstrongswan/library.h +++ b/src/libstrongswan/library.h @@ -233,6 +233,15 @@ enum status_t { NEED_MORE, }; +/** + * used by strict_crl_policy + */ +typedef enum { + STRICT_NO, + STRICT_YES, + STRICT_IFURI +} strict_t; + /** * enum_names for type status_t. */ diff --git a/src/libstrongswan/printf_hook.h b/src/libstrongswan/printf_hook.h index 45184a8f0..03bcf447d 100644 --- a/src/libstrongswan/printf_hook.h +++ b/src/libstrongswan/printf_hook.h @@ -38,30 +38,14 @@ #define PRINTF_IDENTIFICATION 'D' /** 1 argumnet: host_t *host; use #-modifier to include port number */ #define PRINTF_HOST 'H' -/** 1 argument: ike_sa_id_t *id */ -#define PRINTF_IKE_SA_ID 'J' /** 1 argument: ike_sa_t *ike_sa */ -#define PRINTF_IKE_SA 'K' -/** 1 argument: message_t *message */ -#define PRINTF_MESSAGE 'M' -/** 2 arguments: enum_name_t *name, long value */ #define PRINTF_ENUM 'N' /** 1 argument: child_sa_t *child_sa */ -#define PRINTF_CHILD_SA 'P' -/** 1 argument: traffic_selector_t *ts */ #define PRINTF_TRAFFIC_SELECTOR 'R' /** 1 argument: time_t *time; with #-modifier 2 arguments: time_t *time, bool utc */ #define PRINTF_TIME 'T' -/** 1 argument: x509_t *cert; with #-modifier 2 arguments: x509_t *cert, bool utc */ -#define PRINTF_X509 'Q' -/** 1 argument: crl_t *crl; with #-modifier 2 arguments: crl_t *crl, bool utc */ -#define PRINTF_CRL 'U' /** 2 arguments: time_t *begin, time_t *end */ #define PRINTF_TIME_DELTA 'V' -/** 1 argument: ca_info_t *ca_info; with #-modifier 2 arguments: ca_info_t *ca_info, bool utc */ -#define PRINTF_CAINFO 'W' -/** 1 argument: certinfo_t *certinfo; with #-modifier 2 arguments: certinfo_t *certinfo, bool utc */ -#define PRINTF_CERTINFO 'Y' /** * Generic arginfo handlers for printf() hooks diff --git a/src/libstrongswan/utils/fetcher.c b/src/libstrongswan/utils/fetcher.c index 6165cc1e1..7a06999aa 100644 --- a/src/libstrongswan/utils/fetcher.c +++ b/src/libstrongswan/utils/fetcher.c @@ -25,6 +25,9 @@ #endif /* LIBCURL */ #ifdef LIBLDAP +#ifndef LDAP_DEPRECATED +#define LDAP_DEPRECATED 1 +#endif #include #endif /* LIBLDAP */ diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c index 8cbfd6ab8..68e9c9500 100644 --- a/src/libstrongswan/utils/host.c +++ b/src/libstrongswan/utils/host.c @@ -325,7 +325,7 @@ static bool equals(private_host_t *this, private_host_t *other) { if (!ip_equals(this, other)) { - return FAILED; + return FALSE; } switch (this->address.sa_family) diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c index 341af39c0..673cbb828 100644 --- a/src/libstrongswan/utils/identification.c +++ b/src/libstrongswan/utils/identification.c @@ -738,8 +738,15 @@ static bool contains_wildcards(private_identification_t *this) */ static bool equals_binary(private_identification_t *this, private_identification_t *other) { - return this->type == other->type && - chunk_equals(this->encoded, other->encoded); + if (this->type == other->type) + { + if (this->type == ID_ANY) + { + return TRUE; + } + return chunk_equals(this->encoded, other->encoded); + } + return FALSE; } /** @@ -956,7 +963,10 @@ static identification_t *clone_(private_identification_t *this) private_identification_t *clone = identification_create(); clone->type = this->type; - clone->encoded = chunk_clone(this->encoded); + if (this->encoded.len) + { + clone->encoded = chunk_clone(this->encoded); + } clone->public.equals = this->public.equals; clone->public.matches = this->public.matches; -- cgit v1.2.3