diff --git a/NEWS b/NEWS index 0d22295d4..9dd0ed1b4 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,16 @@ +strongswan-5.1.3 +---------------- + +- The acert plugin evaluates X.509 Attribute Certificates. Group membership + information encoded as strings can be used to fulfill authorization checks + defined with the rightgroups option. Attribute Certificates can be loaded + locally or get exchanged in IKEv2 certificate payloads. + +- The pki command gained support to generate X.509 Attribute Certificates + using the --acert subcommand, while the --print command supports the ac type. + The openac utility has been removed in favor of the new pki functionality. + + strongswan-5.1.2 ---------------- diff --git a/conf/options/tools.opt b/conf/options/tools.opt index 23e6a1c9f..72a49de28 100644 --- a/conf/options/tools.opt +++ b/conf/options/tools.opt @@ -1,6 +1,3 @@ -openac.load = - Plugins to load in ipsec openac tool. - pki.load = Plugins to load in ipsec pki tool. diff --git a/configure.ac b/configure.ac index 15d00bdab..e8eb5a67c 100644 --- a/configure.ac +++ b/configure.ac @@ -165,6 +165,7 @@ ARG_ENABL_SET([mysql], [enable MySQL database support. Requires libmysq ARG_ENABL_SET([sqlite], [enable SQLite database support. Requires libsqlite3.]) # authentication/credential plugins ARG_ENABL_SET([addrblock], [enables RFC 3779 address block constraint support.]) +ARG_ENABL_SET([acert], [enable X509 attribute certificate checking plugin.]) ARG_ENABL_SET([agent], [enables the ssh-agent signing plugin.]) ARG_DISBL_SET([constraints], [disable advanced X509 constraint checking plugin.]) ARG_ENABL_SET([coupling], [enable IKEv2 plugin to couple peer certificates permanently to authentication.]) @@ -264,7 +265,7 @@ ARG_ENABL_SET([medsrv], [enable mediation server web frontend and daemon ARG_ENABL_SET([nm], [enable NetworkManager backend.]) ARG_DISBL_SET([scripts], [disable additional utilities (found in directory scripts).]) ARG_ENABL_SET([tkm], [enable Trusted Key Manager support.]) -ARG_DISBL_SET([tools], [disable additional utilities (openac, scepclient and pki).]) +ARG_DISBL_SET([tools], [disable additional utilities (scepclient and pki).]) # optional features ARG_ENABL_SET([bfd-backtraces], [use binutils libbfd to resolve backtraces for memory leaks and segfaults.]) ARG_DISBL_SET([ikev1], [disable IKEv1 protocol support in charon.]) @@ -1052,7 +1053,6 @@ charon_plugins= starter_plugins= pool_plugins= attest_plugins= -openac_plugins= scepclient_plugins= pki_plugins= scripts_plugins= @@ -1068,7 +1068,7 @@ h_plugins= s_plugins= t_plugins= -ADD_PLUGIN([test-vectors], [s charon openac scepclient pki]) +ADD_PLUGIN([test-vectors], [s charon scepclient pki]) ADD_PLUGIN([curl], [s charon scepclient scripts nm cmd]) ADD_PLUGIN([soup], [s charon scripts nm cmd]) ADD_PLUGIN([unbound], [s charon scripts]) @@ -1076,37 +1076,38 @@ ADD_PLUGIN([ldap], [s charon scepclient scripts nm cmd]) ADD_PLUGIN([mysql], [s charon pool manager medsrv attest]) ADD_PLUGIN([sqlite], [s charon pool manager medsrv attest]) ADD_PLUGIN([pkcs11], [s charon pki nm cmd]) -ADD_PLUGIN([aes], [s charon openac scepclient pki scripts nm cmd]) -ADD_PLUGIN([des], [s charon openac scepclient pki scripts nm cmd]) -ADD_PLUGIN([blowfish], [s charon openac scepclient pki scripts nm cmd]) -ADD_PLUGIN([rc2], [s charon openac scepclient pki scripts nm cmd]) -ADD_PLUGIN([sha1], [s charon openac scepclient pki scripts medsrv attest nm cmd]) -ADD_PLUGIN([sha2], [s charon openac scepclient pki scripts medsrv attest nm cmd]) -ADD_PLUGIN([md4], [s charon openac manager scepclient pki nm cmd]) -ADD_PLUGIN([md5], [s charon openac scepclient pki scripts attest nm cmd]) -ADD_PLUGIN([rdrand], [s charon openac scepclient pki scripts medsrv attest nm cmd]) -ADD_PLUGIN([random], [s charon openac scepclient pki scripts medsrv attest nm cmd]) +ADD_PLUGIN([aes], [s charon scepclient pki scripts nm cmd]) +ADD_PLUGIN([des], [s charon scepclient pki scripts nm cmd]) +ADD_PLUGIN([blowfish], [s charon scepclient pki scripts nm cmd]) +ADD_PLUGIN([rc2], [s charon scepclient pki scripts nm cmd]) +ADD_PLUGIN([sha1], [s charon scepclient pki scripts medsrv attest nm cmd]) +ADD_PLUGIN([sha2], [s charon scepclient pki scripts medsrv attest nm cmd]) +ADD_PLUGIN([md4], [s charon manager scepclient pki nm cmd]) +ADD_PLUGIN([md5], [s charon scepclient pki scripts attest nm cmd]) +ADD_PLUGIN([rdrand], [s charon scepclient pki scripts medsrv attest nm cmd]) +ADD_PLUGIN([random], [s charon scepclient pki scripts medsrv attest nm cmd]) ADD_PLUGIN([nonce], [s charon nm cmd]) -ADD_PLUGIN([x509], [s charon openac scepclient pki scripts attest nm cmd]) +ADD_PLUGIN([x509], [s charon scepclient pki scripts attest nm cmd]) ADD_PLUGIN([revocation], [s charon nm cmd]) ADD_PLUGIN([constraints], [s charon nm cmd]) +ADD_PLUGIN([acert], [s charon]) ADD_PLUGIN([pubkey], [s charon cmd]) -ADD_PLUGIN([pkcs1], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) +ADD_PLUGIN([pkcs1], [s charon scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([pkcs7], [s charon scepclient pki scripts nm cmd]) -ADD_PLUGIN([pkcs8], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) +ADD_PLUGIN([pkcs8], [s charon scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([pkcs12], [s charon scepclient pki scripts cmd]) ADD_PLUGIN([pgp], [s charon]) ADD_PLUGIN([dnskey], [s charon pki]) ADD_PLUGIN([sshkey], [s charon pki nm cmd]) ADD_PLUGIN([dnscert], [c charon]) ADD_PLUGIN([ipseckey], [c charon]) -ADD_PLUGIN([pem], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) +ADD_PLUGIN([pem], [s charon scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([padlock], [s charon]) -ADD_PLUGIN([openssl], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) -ADD_PLUGIN([gcrypt], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) -ADD_PLUGIN([af-alg], [s charon openac scepclient pki scripts medsrv attest nm cmd]) +ADD_PLUGIN([openssl], [s charon scepclient pki scripts manager medsrv attest nm cmd]) +ADD_PLUGIN([gcrypt], [s charon scepclient pki scripts manager medsrv attest nm cmd]) +ADD_PLUGIN([af-alg], [s charon scepclient pki scripts medsrv attest nm cmd]) ADD_PLUGIN([fips-prf], [s charon nm cmd]) -ADD_PLUGIN([gmp], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) +ADD_PLUGIN([gmp], [s charon scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([agent], [s charon nm cmd]) ADD_PLUGIN([keychain], [s charon cmd]) ADD_PLUGIN([xcbc], [s charon nm cmd]) @@ -1188,7 +1189,6 @@ AC_SUBST(charon_plugins) AC_SUBST(starter_plugins) AC_SUBST(pool_plugins) AC_SUBST(attest_plugins) -AC_SUBST(openac_plugins) AC_SUBST(scepclient_plugins) AC_SUBST(pki_plugins) AC_SUBST(scripts_plugins) @@ -1229,6 +1229,7 @@ AM_CONDITIONAL(USE_NONCE, test x$nonce = xtrue) AM_CONDITIONAL(USE_X509, test x$x509 = xtrue) AM_CONDITIONAL(USE_REVOCATION, test x$revocation = xtrue) AM_CONDITIONAL(USE_CONSTRAINTS, test x$constraints = xtrue) +AM_CONDITIONAL(USE_ACERT, test x$acert = xtrue) AM_CONDITIONAL(USE_PUBKEY, test x$pubkey = xtrue) AM_CONDITIONAL(USE_PKCS1, test x$pkcs1 = xtrue) AM_CONDITIONAL(USE_PKCS7, test x$pkcs7 = xtrue) @@ -1454,6 +1455,7 @@ AC_CONFIG_FILES([ src/libstrongswan/plugins/x509/Makefile src/libstrongswan/plugins/revocation/Makefile src/libstrongswan/plugins/constraints/Makefile + src/libstrongswan/plugins/acert/Makefile src/libstrongswan/plugins/pubkey/Makefile src/libstrongswan/plugins/pkcs1/Makefile src/libstrongswan/plugins/pkcs7/Makefile @@ -1582,7 +1584,6 @@ AC_CONFIG_FILES([ src/_updown/Makefile src/_updown_espmark/Makefile src/_copyright/Makefile - src/openac/Makefile src/scepclient/Makefile src/pki/Makefile src/pki/man/Makefile @@ -1619,6 +1620,7 @@ AC_CONFIG_FILES([ src/pki/man/pki---req.1 src/pki/man/pki---self.1 src/pki/man/pki---signcrl.1 + src/pki/man/pki---acert.1 src/pki/man/pki---verify.1 ]) diff --git a/packages/strongswan/debian/strongswan-tools.install b/packages/strongswan/debian/strongswan-tools.install index 353a7db8d..1b7872d86 100644 --- a/packages/strongswan/debian/strongswan-tools.install +++ b/packages/strongswan/debian/strongswan-tools.install @@ -1,5 +1,3 @@ usr/lib/strongswan/scepclient usr/lib/strongswan/ -usr/lib/strongswan/openac usr/lib/strongswan/ usr/lib/strongswan/pki usr/lib/strongswan/ usr/share/man/man8/scepclient.8 usr/share/man/man8/ -usr/share/man/man8/openac.8 usr/share/man/man8/ diff --git a/src/Makefile.am b/src/Makefile.am index 7d11893d1..93da4893f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -73,7 +73,7 @@ if USE_UPDOWN endif if USE_TOOLS - SUBDIRS += openac scepclient pki + SUBDIRS += scepclient pki endif if USE_CONFTEST diff --git a/src/checksum/Makefile.am b/src/checksum/Makefile.am index d172b1545..82bbadcf1 100644 --- a/src/checksum/Makefile.am +++ b/src/checksum/Makefile.am @@ -100,7 +100,6 @@ if USE_CMD endif if USE_TOOLS - exes += $(DESTDIR)$(ipsecdir)/openac exes += $(DESTDIR)$(ipsecdir)/scepclient exes += $(DESTDIR)$(bindir)/pki endif diff --git a/src/ipsec/_ipsec.in b/src/ipsec/_ipsec.in index 3c1f99825..61632188a 100644 --- a/src/ipsec/_ipsec.in +++ b/src/ipsec/_ipsec.in @@ -70,7 +70,6 @@ case "$1" in echo " rereadcacerts|rereadaacerts|rereadocspcerts" echo " rereadacerts|rereadcrls|rereadall" echo " purgeocsp|purgecrls|purgecerts|purgeike" - echo " openac" echo " scepclient" echo " secrets" echo " starter" diff --git a/src/libcharon/encoding/payloads/cert_payload.c b/src/libcharon/encoding/payloads/cert_payload.c index a32f5705d..05d41051b 100644 --- a/src/libcharon/encoding/payloads/cert_payload.c +++ b/src/libcharon/encoding/payloads/cert_payload.c @@ -224,6 +224,9 @@ METHOD(cert_payload_t, get_cert, certificate_t*, case ENC_X509_SIGNATURE: type = CERT_X509; break; + case ENC_X509_ATTRIBUTE: + type = CERT_X509_AC; + break; case ENC_CRL: type = CERT_X509_CRL; break; @@ -333,6 +336,9 @@ cert_payload_t *cert_payload_create_from_cert(payload_type_t type, case CERT_X509: this->encoding = ENC_X509_SIGNATURE; break; + case CERT_X509_AC: + this->encoding = ENC_X509_ATTRIBUTE; + break; default: DBG1(DBG_ENC, "embedding %N certificate in payload failed", certificate_type_names, cert->get_type(cert)); @@ -380,4 +386,3 @@ cert_payload_t *cert_payload_create_custom(payload_type_t type, return &this->public; } - diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c index ea168058f..991bed116 100644 --- a/src/libcharon/plugins/stroke/stroke_list.c +++ b/src/libcharon/plugins/stroke/stroke_list.c @@ -31,8 +31,9 @@ #include #include #include -#include #include +#include +#include /* warning intervals for list functions */ #define CERT_WARNING_INTERVAL 30 /* days */ @@ -1027,16 +1028,19 @@ static void stroke_list_certs(linked_list_t *list, char *label, static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out) { bool first = TRUE; - time_t thisUpdate, nextUpdate, now = time(NULL); - enumerator_t *enumerator = list->create_enumerator(list); + time_t notBefore, notAfter, now = time(NULL); + enumerator_t *enumerator; certificate_t *cert; - while (enumerator->enumerate(enumerator, (void**)&cert)) + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &cert)) { ac_t *ac = (ac_t*)cert; + ac_group_type_t type; identification_t *id; - ietf_attributes_t *groups; + enumerator_t *groups; chunk_t chunk; + bool firstgroup = TRUE; if (first) { @@ -1061,30 +1065,78 @@ static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out) { fprintf(out, " hserial: %#B\n", &chunk); } - groups = ac->get_groups(ac); - if (groups) + groups = ac->create_group_enumerator(ac); + while (groups->enumerate(groups, &type, &chunk)) { - fprintf(out, " groups: %s\n", groups->get_string(groups)); - groups->destroy(groups); + int oid; + char *str; + + if (firstgroup) + { + fprintf(out, " groups: "); + firstgroup = FALSE; + } + else + { + fprintf(out, " "); + } + switch (type) + { + case AC_GROUP_TYPE_STRING: + fprintf(out, "%.*s", (int)chunk.len, chunk.ptr); + break; + case AC_GROUP_TYPE_OID: + oid = asn1_known_oid(chunk); + if (oid == OID_UNKNOWN) + { + str = asn1_oid_to_string(chunk); + if (str) + { + fprintf(out, "%s", str); + } + else + { + fprintf(out, "OID:%#B", &chunk); + } + } + else + { + fprintf(out, "%s", oid_names[oid].name); + } + break; + case AC_GROUP_TYPE_OCTETS: + fprintf(out, "%#B", &chunk); + break; + } + fprintf(out, "\n"); } + groups->destroy(groups); fprintf(out, " issuer: \"%Y\"\n", cert->get_issuer(cert)); chunk = chunk_skip_zero(ac->get_serial(ac)); fprintf(out, " serial: %#B\n", &chunk); /* list validity */ - cert->get_validity(cert, &now, &thisUpdate, &nextUpdate); - fprintf(out, " updates: this %T\n", &thisUpdate, utc); - fprintf(out, " next %T, ", &nextUpdate, utc); - if (now > nextUpdate) + cert->get_validity(cert, &now, ¬Before, ¬After); + fprintf(out, " validity: not before %T, ", ¬Before, utc); + if (now < notBefore) { - fprintf(out, "expired (%V ago)\n", &now, &nextUpdate); + fprintf(out, "not valid yet (valid in %V)\n", &now, ¬Before); + } + else + { + fprintf(out, "ok\n"); + } + fprintf(out, " not after %T, ", ¬After, utc); + if (now > notAfter) + { + fprintf(out, "expired (%V ago)\n", &now, ¬After); } else { fprintf(out, "ok"); - if (now > nextUpdate - AC_WARNING_INTERVAL * 60 * 60 * 24) + if (now > notAfter - AC_WARNING_INTERVAL * 60 * 60 * 24) { - fprintf(out, " (expires in %V)", &now, &nextUpdate); + fprintf(out, " (expires in %V)", &now, ¬After); } fprintf(out, " \n"); } diff --git a/src/libcharon/sa/ikev2/tasks/ike_cert_post.c b/src/libcharon/sa/ikev2/tasks/ike_cert_post.c index a93e5137e..6dbc4dec3 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_cert_post.c +++ b/src/libcharon/sa/ikev2/tasks/ike_cert_post.c @@ -22,6 +22,7 @@ #include #include #include +#include typedef struct private_ike_cert_post_t private_ike_cert_post_t; @@ -104,6 +105,102 @@ static cert_payload_t *build_cert_payload(private_ike_cert_post_t *this, return payload; } +/** + * Add subject certificate to message + */ +static bool add_subject_cert(private_ike_cert_post_t *this, auth_cfg_t *auth, + message_t *message) +{ + cert_payload_t *payload; + certificate_t *cert; + + cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (!cert) + { + return FALSE; + } + payload = build_cert_payload(this, cert); + if (!payload) + { + return FALSE; + } + DBG1(DBG_IKE, "sending end entity cert \"%Y\"", cert->get_subject(cert)); + message->add_payload(message, (payload_t*)payload); + return TRUE; +} + +/** + * Add intermediate CA certificates to message + */ +static void add_im_certs(private_ike_cert_post_t *this, auth_cfg_t *auth, + message_t *message) +{ + cert_payload_t *payload; + enumerator_t *enumerator; + certificate_t *cert; + auth_rule_t type; + + enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &type, &cert)) + { + if (type == AUTH_RULE_IM_CERT) + { + payload = cert_payload_create_from_cert(CERTIFICATE, cert); + if (payload) + { + DBG1(DBG_IKE, "sending issuer cert \"%Y\"", + cert->get_subject(cert)); + message->add_payload(message, (payload_t*)payload); + } + } + } + enumerator->destroy(enumerator); +} + +/** + * Add any valid attribute certificates of subject to message + */ +static void add_attribute_certs(private_ike_cert_post_t *this, + auth_cfg_t *auth, message_t *message) +{ + certificate_t *subject, *cert; + + subject = auth->get(auth, AUTH_RULE_SUBJECT_CERT); + if (subject && subject->get_type(subject) == CERT_X509) + { + x509_t *x509 = (x509_t*)subject; + identification_t *id, *serial; + enumerator_t *enumerator; + cert_payload_t *payload; + ac_t *ac; + + /* we look for attribute certs having our serial and holder issuer, + * which is recommended by RFC 5755 */ + serial = identification_create_from_encoding(ID_KEY_ID, + x509->get_serial(x509)); + enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, + CERT_X509_AC, KEY_ANY, serial, FALSE); + while (enumerator->enumerate(enumerator, &ac)) + { + cert = &ac->certificate; + id = ac->get_holderIssuer(ac); + if (id && id->equals(id, subject->get_issuer(subject)) && + cert->get_validity(cert, NULL, NULL, NULL)) + { + payload = cert_payload_create_from_cert(CERTIFICATE, cert); + if (payload) + { + DBG1(DBG_IKE, "sending attribute certificate " + "issued by \"%Y\"", cert->get_issuer(cert)); + message->add_payload(message, (payload_t*)payload); + } + } + } + enumerator->destroy(enumerator); + serial->destroy(serial); + } +} + /** * add certificates to message */ @@ -111,6 +208,7 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message) { peer_cfg_t *peer_cfg; auth_payload_t *payload; + auth_cfg_t *auth; payload = (auth_payload_t*)message->get_payload(message, AUTHENTICATION); peer_cfg = this->ike_sa->get_peer_cfg(this->ike_sa); @@ -130,46 +228,13 @@ static void build_certs(private_ike_cert_post_t *this, message_t *message) } /* FALL */ case CERT_ALWAYS_SEND: - { - cert_payload_t *payload; - enumerator_t *enumerator; - certificate_t *cert; - auth_rule_t type; - auth_cfg_t *auth; - auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE); - - /* get subject cert first, then issuing certificates */ - cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); - if (!cert) + if (add_subject_cert(this, auth, message)) { - break; + add_im_certs(this, auth, message); + add_attribute_certs(this, auth, message); } - payload = build_cert_payload(this, cert); - if (!payload) - { - break; - } - DBG1(DBG_IKE, "sending end entity cert \"%Y\"", - cert->get_subject(cert)); - message->add_payload(message, (payload_t*)payload); - - enumerator = auth->create_enumerator(auth); - while (enumerator->enumerate(enumerator, &type, &cert)) - { - if (type == AUTH_RULE_IM_CERT) - { - payload = cert_payload_create_from_cert(CERTIFICATE, cert); - if (payload) - { - DBG1(DBG_IKE, "sending issuer cert \"%Y\"", - cert->get_subject(cert)); - message->add_payload(message, (payload_t*)payload); - } - } - } - enumerator->destroy(enumerator); - } + break; } } diff --git a/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c index bd28b29d7..558b1e914 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c +++ b/src/libcharon/sa/ikev2/tasks/ike_cert_pre.c @@ -259,6 +259,30 @@ static void process_crl(cert_payload_t *payload, auth_cfg_t *auth) } } +/** + * Process an attribute certificate payload + */ +static void process_ac(cert_payload_t *payload, auth_cfg_t *auth) +{ + certificate_t *cert; + + cert = payload->get_cert(payload); + if (cert) + { + if (cert->get_issuer(cert)) + { + DBG1(DBG_IKE, "received attribute certificate issued by \"%Y\"", + cert->get_issuer(cert)); + } + else if (cert->get_subject(cert)) + { + DBG1(DBG_IKE, "received attribute certificate for \"%Y\"", + cert->get_subject(cert)); + } + auth->add(auth, AUTH_HELPER_AC_CERT, cert); + } +} + /** * Process certificate payloads */ @@ -298,13 +322,15 @@ static void process_certs(private_ike_cert_pre_t *this, message_t *message) case ENC_CRL: process_crl(cert_payload, auth); break; + case ENC_X509_ATTRIBUTE: + process_ac(cert_payload, auth); + break; case ENC_PKCS7_WRAPPED_X509: case ENC_PGP: case ENC_DNS_SIGNED_KEY: case ENC_KERBEROS_TOKEN: case ENC_ARL: case ENC_SPKI: - case ENC_X509_ATTRIBUTE: case ENC_RAW_RSA_KEY: case ENC_X509_HASH_AND_URL_BUNDLE: case ENC_OCSP_CONTENT: diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk index 440913071..2b58db554 100644 --- a/src/libstrongswan/Android.mk +++ b/src/libstrongswan/Android.mk @@ -20,7 +20,7 @@ credentials/keys/public_key.c credentials/keys/shared_key.c \ credentials/certificates/certificate.c credentials/certificates/crl.c \ credentials/certificates/ocsp_response.c \ credentials/containers/container.c credentials/containers/pkcs12.c \ -credentials/ietf_attributes/ietf_attributes.c credentials/credential_manager.c \ +credentials/credential_manager.c \ credentials/sets/auth_cfg_wrapper.c credentials/sets/ocsp_response_wrapper.c \ credentials/sets/cert_cache.c credentials/sets/mem_cred.c \ credentials/sets/callback_cred.c credentials/auth_cfg.c database/database.c \ diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index b3a4eda99..3462d2ffc 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -18,7 +18,7 @@ credentials/keys/public_key.c credentials/keys/shared_key.c \ credentials/certificates/certificate.c credentials/certificates/crl.c \ credentials/certificates/ocsp_response.c \ credentials/containers/container.c credentials/containers/pkcs12.c \ -credentials/ietf_attributes/ietf_attributes.c credentials/credential_manager.c \ +credentials/credential_manager.c \ credentials/sets/auth_cfg_wrapper.c credentials/sets/ocsp_response_wrapper.c \ credentials/sets/cert_cache.c credentials/sets/mem_cred.c \ credentials/sets/callback_cred.c credentials/auth_cfg.c database/database.c \ @@ -61,7 +61,6 @@ credentials/certificates/ocsp_response.h \ credentials/certificates/pgp_certificate.h \ credentials/containers/container.h credentials/containers/pkcs7.h \ credentials/containers/pkcs12.h \ -credentials/ietf_attributes/ietf_attributes.h \ credentials/credential_manager.h credentials/sets/auth_cfg_wrapper.h \ credentials/sets/ocsp_response_wrapper.h credentials/sets/cert_cache.h \ credentials/sets/mem_cred.h credentials/sets/callback_cred.h \ @@ -308,6 +307,13 @@ if MONOLITHIC endif endif +if USE_ACERT + SUBDIRS += plugins/acert +if MONOLITHIC + libstrongswan_la_LIBADD += plugins/acert/libstrongswan-acert.la +endif +endif + if USE_PUBKEY SUBDIRS += plugins/pubkey if MONOLITHIC diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c index 2203519e2..4ff9aa6dd 100644 --- a/src/libstrongswan/credentials/auth_cfg.c +++ b/src/libstrongswan/credentials/auth_cfg.c @@ -31,7 +31,7 @@ ENUM(auth_class_names, AUTH_CLASS_ANY, AUTH_CLASS_XAUTH, "XAuth", ); -ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT, +ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_AC_CERT, "RULE_IDENTITY", "RULE_IDENTITY_LOOSE", "RULE_AUTH_CLASS", @@ -56,6 +56,7 @@ ENUM(auth_rule_names, AUTH_RULE_IDENTITY, AUTH_HELPER_REVOCATION_CERT, "HELPER_IM_HASH_URL", "HELPER_SUBJECT_HASH_URL", "HELPER_REVOCATION_CERT", + "HELPER_AC_CERT", ); /** @@ -91,6 +92,7 @@ static inline bool is_multi_value_rule(auth_rule_t type) case AUTH_HELPER_IM_CERT: case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_REVOCATION_CERT: + case AUTH_HELPER_AC_CERT: return TRUE; } return FALSE; @@ -224,6 +226,7 @@ static void init_entry(entry_t *this, auth_rule_t type, va_list args) case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: case AUTH_HELPER_REVOCATION_CERT: + case AUTH_HELPER_AC_CERT: /* pointer type */ this->value = va_arg(args, void*); break; @@ -262,6 +265,7 @@ static bool entry_equals(entry_t *e1, entry_t *e2) case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_REVOCATION_CERT: + case AUTH_HELPER_AC_CERT: { certificate_t *c1, *c2; @@ -319,6 +323,7 @@ static void destroy_entry_value(entry_t *entry) case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_REVOCATION_CERT: + case AUTH_HELPER_AC_CERT: { certificate_t *cert = (certificate_t*)entry->value; cert->destroy(cert); @@ -390,6 +395,7 @@ static void replace(private_auth_cfg_t *this, entry_enumerator_t *enumerator, case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: case AUTH_HELPER_REVOCATION_CERT: + case AUTH_HELPER_AC_CERT: /* pointer type */ entry->value = va_arg(args, void*); break; @@ -467,6 +473,7 @@ METHOD(auth_cfg_t, get, void*, case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: case AUTH_HELPER_REVOCATION_CERT: + case AUTH_HELPER_AC_CERT: case AUTH_RULE_MAX: break; } @@ -736,6 +743,7 @@ METHOD(auth_cfg_t, complies, bool, case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: case AUTH_HELPER_REVOCATION_CERT: + case AUTH_HELPER_AC_CERT: case AUTH_RULE_MAX: /* skip helpers */ continue; @@ -868,6 +876,7 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_REVOCATION_CERT: + case AUTH_HELPER_AC_CERT: { certificate_t *cert = (certificate_t*)value; @@ -1029,6 +1038,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, case AUTH_HELPER_IM_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_REVOCATION_CERT: + case AUTH_HELPER_AC_CERT: { certificate_t *cert = (certificate_t*)value; clone->add(clone, type, cert->get_ref(cert)); diff --git a/src/libstrongswan/credentials/auth_cfg.h b/src/libstrongswan/credentials/auth_cfg.h index d87935589..95b36d706 100644 --- a/src/libstrongswan/credentials/auth_cfg.h +++ b/src/libstrongswan/credentials/auth_cfg.h @@ -117,6 +117,8 @@ enum auth_rule_t { AUTH_HELPER_SUBJECT_HASH_URL, /** revocation certificate (CRL, OCSP), certificate_t* */ AUTH_HELPER_REVOCATION_CERT, + /** attribute certificate for authorization decisions, certificate_t */ + AUTH_HELPER_AC_CERT, /** helper to determine the number of elements in this enum */ AUTH_RULE_MAX, diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c index 4e52272a7..ddb64ef88 100644 --- a/src/libstrongswan/credentials/builder.c +++ b/src/libstrongswan/credentials/builder.c @@ -38,7 +38,7 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END, "BUILD_SERIAL", "BUILD_DIGEST_ALG", "BUILD_ENCRYPTION_ALG", - "BUILD_IETF_GROUP_ATTR", + "BUILD_AC_GROUP_STRINGS", "BUILD_CA_CERT", "BUILD_CERT", "BUILD_CRL_DISTRIBUTION_POINTS", @@ -72,4 +72,3 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END, "BUILD_THRESHOLD", "BUILD_END", ); - diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h index 103b823c0..627e0934d 100644 --- a/src/libstrongswan/credentials/builder.h +++ b/src/libstrongswan/credentials/builder.h @@ -87,8 +87,8 @@ enum builder_part_t { BUILD_DIGEST_ALG, /** encryption algorithm to use, encryption_algorithm_t */ BUILD_ENCRYPTION_ALG, - /** a comma-separated list of ietf group attributes, char* */ - BUILD_IETF_GROUP_ATTR, + /** list of AC group memberships, linked_list_t* with char* */ + BUILD_AC_GROUP_STRINGS, /** a ca certificate, certificate_t* */ BUILD_CA_CERT, /** a certificate, certificate_t* */ diff --git a/src/libstrongswan/credentials/certificates/ac.h b/src/libstrongswan/credentials/certificates/ac.h index 57b44adca..9a3d8f0b9 100644 --- a/src/libstrongswan/credentials/certificates/ac.h +++ b/src/libstrongswan/credentials/certificates/ac.h @@ -24,9 +24,18 @@ #include #include -#include typedef struct ac_t ac_t; +typedef enum ac_group_type_t ac_group_type_t; + +/** + * Common group types, from IETF Attributes Syntax + */ +enum ac_group_type_t { + AC_GROUP_TYPE_OCTETS, + AC_GROUP_TYPE_STRING, + AC_GROUP_TYPE_OID, +}; /** * X.509 attribute certificate interface. @@ -70,19 +79,11 @@ struct ac_t { chunk_t (*get_authKeyIdentifier)(ac_t *this); /** - * Get the group memberships as a list of IETF attributes + * Create an enumerator of contained Group memberships. * - * @return object containing a list of IETF attributes + * @return enumerator over (ac_group_type_t, chunk_t) */ - ietf_attributes_t* (*get_groups)(ac_t *this); - - /** - * @brief Checks if two attribute certificates belong to the same holder - * - * @param that other attribute certificate - * @return TRUE if same holder - */ - bool (*equals_holder) (ac_t *this, ac_t *other); + enumerator_t* (*create_group_enumerator)(ac_t *this); }; #endif /** AC_H_ @}*/ diff --git a/src/libstrongswan/credentials/ietf_attributes/ietf_attributes.c b/src/libstrongswan/credentials/ietf_attributes/ietf_attributes.c deleted file mode 100644 index 49af5a079..000000000 --- a/src/libstrongswan/credentials/ietf_attributes/ietf_attributes.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Copyright (C) 2007-2009 Andreas Steffen - * - * HSR Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * 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 "ietf_attributes.h" - -/** - * Private definition of IETF attribute types - */ -typedef enum { - IETF_ATTRIBUTE_OCTETS = 0, - IETF_ATTRIBUTE_OID = 1, - IETF_ATTRIBUTE_STRING = 2 -} ietf_attribute_type_t; - -typedef struct ietf_attr_t ietf_attr_t; - -/** - * Private definition of an IETF attribute - */ -struct ietf_attr_t { - /** - * IETF attribute type - */ - ietf_attribute_type_t type; - - /** - * IETF attribute value - */ - chunk_t value; - - /** - * Compares two IETF attributes - * - * return -1 if this is earlier in the alphabet than other - * return 0 if this equals other - * return +1 if this is later in the alphabet than other - * - * @param other other object - */ - int (*compare) (ietf_attr_t *this, ietf_attr_t *other); - - /** - * Destroys an ietf_attr_t object. - */ - void (*destroy) (ietf_attr_t *this); -}; - -/** - * Implements ietf_attr_t.compare. - */ -static int ietf_attr_compare(ietf_attr_t *this, ietf_attr_t *other) -{ - int cmp_len, len, cmp_value; - - /* OID attributes are appended after STRING and OCTETS attributes */ - if (this->type != IETF_ATTRIBUTE_OID && other->type == IETF_ATTRIBUTE_OID) - { - return -1; - } - if (this->type == IETF_ATTRIBUTE_OID && other->type != IETF_ATTRIBUTE_OID) - { - return 1; - } - - cmp_len = this->value.len - other->value.len; - len = (cmp_len < 0) ? this->value.len : other->value.len; - cmp_value = memcmp(this->value.ptr, other->value.ptr, len); - - return (cmp_value == 0) ? cmp_len : cmp_value; -} - -/** - * Implements ietf_attr_t.destroy. - */ -static void ietf_attr_destroy(ietf_attr_t *this) -{ - free(this->value.ptr); - free(this); -} - -/** - * Creates an ietf_attr_t object. - */ -static ietf_attr_t* ietf_attr_create(ietf_attribute_type_t type, chunk_t value) -{ - ietf_attr_t *this; - - INIT(this, - .compare = ietf_attr_compare, - .destroy = ietf_attr_destroy, - .type = type, - .value = chunk_clone(value), - ); - - return this; -} - -typedef struct private_ietf_attributes_t private_ietf_attributes_t; - -/** - * Private data of an ietf_attributes_t object. - */ -struct private_ietf_attributes_t { - /** - * Public interface. - */ - ietf_attributes_t public; - - /** - * Printable representation of the IETF attributes - */ - char *string; - - /** - * Linked list of IETF attributes. - */ - linked_list_t *list; - - /** - * reference count - */ - refcount_t ref; -}; - -METHOD(ietf_attributes_t, get_string, char*, - private_ietf_attributes_t *this) -{ - if (this->string == NULL) - { - char buf[BUF_LEN]; - char *pos = buf; - int len = BUF_LEN; - bool first = TRUE; - ietf_attr_t *attr; - enumerator_t *enumerator; - - enumerator = this->list->create_enumerator(this->list); - while (enumerator->enumerate(enumerator, &attr)) - { - int written; - - if (first) - { - first = FALSE; - } - else - { - written = snprintf(pos, len, ", "); - if (written < 0 || written >= len) - { - break; - } - pos += written; - len -= written; - } - - switch (attr->type) - { - case IETF_ATTRIBUTE_OCTETS: - case IETF_ATTRIBUTE_STRING: - written = snprintf(pos, len, "%.*s", (int)attr->value.len, - attr->value.ptr); - break; - case IETF_ATTRIBUTE_OID: - { - int oid = asn1_known_oid(attr->value); - - if (oid == OID_UNKNOWN) - { - written = snprintf(pos, len, "0x%#B", &attr->value); - } - else - { - written = snprintf(pos, len, "%s", oid_names[oid].name); - } - break; - } - default: - written = 0; - break; - } - if (written < 0 || written >= len) - { - break; - } - pos += written; - len -= written; - } - enumerator->destroy(enumerator); - if (len < BUF_LEN) - { - this->string = strdup(buf); - } - } - return this->string; -} - -METHOD(ietf_attributes_t, get_encoding, chunk_t, - private_ietf_attributes_t *this) -{ - chunk_t values; - size_t size = 0; - u_char *pos; - ietf_attr_t *attr; - enumerator_t *enumerator; - - /* precalculate the total size of all values */ - enumerator = this->list->create_enumerator(this->list); - while (enumerator->enumerate(enumerator, &attr)) - { - size_t len = attr->value.len; - - size += 1 + (len > 0) + (len >= 128) + (len >= 256) + (len >= 65536) + len; - } - enumerator->destroy(enumerator); - - pos = asn1_build_object(&values, ASN1_SEQUENCE, size); - - enumerator = this->list->create_enumerator(this->list); - while (enumerator->enumerate(enumerator, &attr)) - { - chunk_t ietfAttribute; - asn1_t type = ASN1_NULL; - - switch (attr->type) - { - case IETF_ATTRIBUTE_OCTETS: - type = ASN1_OCTET_STRING; - break; - case IETF_ATTRIBUTE_STRING: - type = ASN1_UTF8STRING; - break; - case IETF_ATTRIBUTE_OID: - type = ASN1_OID; - break; - } - ietfAttribute = asn1_simple_object(type, attr->value); - - /* copy ietfAttribute into values chunk */ - memcpy(pos, ietfAttribute.ptr, ietfAttribute.len); - pos += ietfAttribute.len; - free(ietfAttribute.ptr); - } - enumerator->destroy(enumerator); - - return asn1_wrap(ASN1_SEQUENCE, "m", values); -} - -/** - * Implementation of ietf_attributes_t.equals. - */ -static bool equals(private_ietf_attributes_t *this, - private_ietf_attributes_t *other) -{ - bool result = TRUE; - - /* lists must have the same number of attributes */ - if (other == NULL || - this->list->get_count(this->list) != other->list->get_count(other->list)) - { - return FALSE; - } - - /* compare two alphabetically-sorted lists */ - { - ietf_attr_t *attr_a, *attr_b; - enumerator_t *enum_a, *enum_b; - - enum_a = this->list->create_enumerator(this->list); - enum_b = other->list->create_enumerator(other->list); - while (enum_a->enumerate(enum_a, &attr_a) && - enum_b->enumerate(enum_b, &attr_b)) - { - if (attr_a->compare(attr_a, attr_b) != 0) - { - /* we have a mismatch */ - result = FALSE; - break; - } - } - enum_a->destroy(enum_a); - enum_b->destroy(enum_b); - } - return result; -} - -/** - * Implementation of ietf_attributes_t.matches. - */ -static bool matches(private_ietf_attributes_t *this, - private_ietf_attributes_t *other) -{ - bool result = FALSE; - ietf_attr_t *attr_a, *attr_b; - enumerator_t *enum_a, *enum_b; - - /* always match if this->list does not contain any attributes */ - if (this->list->get_count(this->list) == 0) - { - return TRUE; - } - - /* never match if other->list does not contain any attributes */ - if (other == NULL || other->list->get_count(other->list) == 0) - { - return FALSE; - } - - /* get first attribute from both lists */ - enum_a = this->list->create_enumerator(this->list); - enum_a->enumerate(enum_a, &attr_a); - enum_b = other->list->create_enumerator(other->list); - enum_b->enumerate(enum_b, &attr_b); - - /* look for at least one common attribute */ - while (TRUE) - { - int cmp = attr_a->compare(attr_a, attr_b); - - if (cmp == 0) - { - /* we have a match */ - result = TRUE; - break; - } - if (cmp == -1) - { - /* attr_a is earlier in the alphabet, get next attr_a */ - if (!enum_a->enumerate(enum_a, &attr_a)) - { - /* we have reached the end of enum_a */ - break; - } - } - else - { - /* attr_a is later in the alphabet, get next attr_b */ - if (!enum_b->enumerate(enum_b, &attr_b)) - { - /* we have reached the end of enum_b */ - break; - } - } - } - enum_a->destroy(enum_a); - enum_b->destroy(enum_b); - - return result; -} - -METHOD(ietf_attributes_t, get_ref, ietf_attributes_t*, - private_ietf_attributes_t *this) -{ - ref_get(&this->ref); - return &this->public; -} - -METHOD(ietf_attributes_t, destroy, void, - private_ietf_attributes_t *this) -{ - if (ref_put(&this->ref)) - { - this->list->destroy_offset(this->list, offsetof(ietf_attr_t, destroy)); - free(this->string); - free(this); - } -} - -static private_ietf_attributes_t* create_empty(void) -{ - private_ietf_attributes_t *this; - - INIT(this, - .public = { - .get_string = _get_string, - .get_encoding = _get_encoding, - .equals = (bool (*)(ietf_attributes_t*,ietf_attributes_t*))equals, - .matches = (bool (*)(ietf_attributes_t*,ietf_attributes_t*))matches, - .get_ref = _get_ref, - .destroy = _destroy, - }, - .list = linked_list_create(), - .ref = 1, - ); - - return this; -} - -/** - * Adds an ietf_attr_t object to a sorted linked list - */ -static void ietf_attributes_add(private_ietf_attributes_t *this, - ietf_attr_t *attr) -{ - ietf_attr_t *current_attr; - enumerator_t *enumerator; - int cmp = -1; - - enumerator = this->list->create_enumerator(this->list); - while (enumerator->enumerate(enumerator, (void **)¤t_attr) && - (cmp = attr->compare(attr, current_attr)) > 0) - { - continue; - } - if (cmp == 0) - { - attr->destroy(attr); - } - else - { /* the enumerator either points to the end or to the attribute > attr */ - this->list->insert_before(this->list, enumerator, attr); - } - enumerator->destroy(enumerator); -} - -/* - * Described in header. - */ -ietf_attributes_t *ietf_attributes_create_from_string(char *string) -{ - private_ietf_attributes_t *this = create_empty(); - - chunk_t line = { string, strlen(string) }; - - while (eat_whitespace(&line)) - { - chunk_t group; - - /* extract the next comma-separated group attribute */ - if (!extract_token(&group, ',', &line)) - { - group = line; - line.len = 0; - } - - /* remove any trailing spaces */ - while (group.len > 0 && *(group.ptr + group.len - 1) == ' ') - { - group.len--; - } - - /* add the group attribute to the list */ - if (group.len > 0) - { - ietf_attr_t *attr = ietf_attr_create(IETF_ATTRIBUTE_STRING, group); - - ietf_attributes_add(this, attr); - } - } - - return &(this->public); -} - -/** - * 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 */ - { 0, "exit", ASN1_EOC, ASN1_EXIT } -}; -#define IETF_ATTR_OCTETS 4 -#define IETF_ATTR_OID 6 -#define IETF_ATTR_STRING 8 - -/* - * Described in header. - */ -ietf_attributes_t *ietf_attributes_create_from_encoding(chunk_t encoded) -{ - private_ietf_attributes_t *this = create_empty(); - asn1_parser_t *parser; - chunk_t object; - int objectID; - - parser = asn1_parser_create(ietfAttrSyntaxObjects, encoded); - while (parser->iterate(parser, &objectID, &object)) - { - switch (objectID) - { - case IETF_ATTR_OCTETS: - case IETF_ATTR_OID: - case IETF_ATTR_STRING: - { - ietf_attribute_type_t type; - ietf_attr_t *attr; - - type = (objectID - IETF_ATTR_OCTETS) / 2; - attr = ietf_attr_create(type, object); - ietf_attributes_add(this, attr); - } - break; - default: - break; - } - } - parser->destroy(parser); - - return &(this->public); -} - diff --git a/src/libstrongswan/credentials/ietf_attributes/ietf_attributes.h b/src/libstrongswan/credentials/ietf_attributes/ietf_attributes.h deleted file mode 100644 index ab6bae984..000000000 --- a/src/libstrongswan/credentials/ietf_attributes/ietf_attributes.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2007-2009 Andreas Steffen - * - * HSR Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * 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. - */ - -/** - * @defgroup ietf_attributes ietf_attributes - * @{ @ingroup credentials - */ - -#ifndef IETF_ATTRIBUTES_H_ -#define IETF_ATTRIBUTES_H_ - -typedef struct ietf_attributes_t ietf_attributes_t; - -#include - -/** - * - */ -struct ietf_attributes_t { - - /** - * Get the an alphabetically sorted list of printable IETF attributes. - * - * Result points to internal data, do not free. - * - * @return a string containing printable attributes - */ - char* (*get_string) (ietf_attributes_t *this); - - /** - * Get the ASN.1 encoding of the IETF attributes. - * - * @return allocated chunk containing the encoded bytes - */ - chunk_t (*get_encoding) (ietf_attributes_t *this); - - /** - * Check for equality between two lists. - * - * @param other attribute list to be checked for equality - * @return TRUE if equal - */ - bool (*equals) (ietf_attributes_t *this, ietf_attributes_t *other); - - /** - * Check for common attributes between two lists. - * - * @param other attribute list to be matched - * @return TRUE if there is at least a common attribute - */ - bool (*matches) (ietf_attributes_t *this, ietf_attributes_t *other); - - /** - * Get a new reference to the IETF attributes. - * - * @return this, with an increased refcount - */ - ietf_attributes_t* (*get_ref)(ietf_attributes_t *this); - - /** - * Destroys an ietf_attributes_t object. - */ - void (*destroy) (ietf_attributes_t *this); -}; - -/** - * @param string input string, which will be converted - * @return ietf_attributes_t - */ -ietf_attributes_t *ietf_attributes_create_from_string(char *string); - -/** - * @param encoded ASN.1 encoded bytes, such as from ietf_attributes.get_encoding - * @return ietf_attributes_t - */ -ietf_attributes_t *ietf_attributes_create_from_encoding(chunk_t encoded); - -#endif /** IETF_ATTRIBUTES_H_ @}*/ - diff --git a/src/libstrongswan/credentials/sets/auth_cfg_wrapper.c b/src/libstrongswan/credentials/sets/auth_cfg_wrapper.c index 46bfb5c6e..c6b8d0c7e 100644 --- a/src/libstrongswan/credentials/sets/auth_cfg_wrapper.c +++ b/src/libstrongswan/credentials/sets/auth_cfg_wrapper.c @@ -133,7 +133,8 @@ static bool enumerate(wrapper_enumerator_t *this, certificate_t **cert) } else if (rule != AUTH_HELPER_SUBJECT_CERT && rule != AUTH_HELPER_IM_CERT && - rule != AUTH_HELPER_REVOCATION_CERT) + rule != AUTH_HELPER_REVOCATION_CERT && + rule != AUTH_HELPER_AC_CERT) { /* handle only HELPER certificates */ continue; } diff --git a/src/libstrongswan/plugins/acert/Makefile.am b/src/libstrongswan/plugins/acert/Makefile.am new file mode 100644 index 000000000..ba16f413a --- /dev/null +++ b/src/libstrongswan/plugins/acert/Makefile.am @@ -0,0 +1,17 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = \ + -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-acert.la +else +plugin_LTLIBRARIES = libstrongswan-acert.la +endif + +libstrongswan_acert_la_SOURCES = \ + acert_validator.h acert_validator.c \ + acert_plugin.h acert_plugin.c + +libstrongswan_acert_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/acert/acert_plugin.c b/src/libstrongswan/plugins/acert/acert_plugin.c new file mode 100644 index 000000000..01d9ae3b8 --- /dev/null +++ b/src/libstrongswan/plugins/acert/acert_plugin.c @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 . + * + * 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 "acert_plugin.h" +#include "acert_validator.h" + +#include + +typedef struct private_acert_plugin_t private_acert_plugin_t; + +/** + * private data of acert_plugin + */ +struct private_acert_plugin_t { + + /** + * public functions + */ + acert_plugin_t public; + + /** + * Validator implementation instance. + */ + acert_validator_t *validator; +}; + +METHOD(plugin_t, get_name, char*, + private_acert_plugin_t *this) +{ + return "acert"; +} + +/** + * Register validator + */ +static bool plugin_cb(private_acert_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); + } + else + { + lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_acert_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "acert"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_acert_plugin_t *this) +{ + this->validator->destroy(this->validator); + free(this); +} + +/* + * see header file + */ +plugin_t *acert_plugin_create() +{ + private_acert_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + .validator = acert_validator_create(), + ); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/acert/acert_plugin.h b/src/libstrongswan/plugins/acert/acert_plugin.h new file mode 100644 index 000000000..97d12936d --- /dev/null +++ b/src/libstrongswan/plugins/acert/acert_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 . + * + * 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 acert acert + * @ingroup plugins + * + * @defgroup acert_plugin acert_plugin + * @{ @ingroup acert + */ + +#ifndef ACERT_PLUGIN_H_ +#define ACERT_PLUGIN_H_ + +#include + +typedef struct acert_plugin_t acert_plugin_t; + +/** + * X.509 attribute certificate group membership checking. + */ +struct acert_plugin_t { + + /** + * Implements plugin_t. interface. + */ + plugin_t plugin; +}; + +#endif /** ACERT_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/acert/acert_validator.c b/src/libstrongswan/plugins/acert/acert_validator.c new file mode 100644 index 000000000..ab15dba98 --- /dev/null +++ b/src/libstrongswan/plugins/acert/acert_validator.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 . + * + * 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. + */ + +#define _GNU_SOURCE +#include + +#include "acert_validator.h" + +#include +#include + +typedef struct private_acert_validator_t private_acert_validator_t; + +/** + * Private data of an acert_validator_t object. + */ +struct private_acert_validator_t { + + /** + * Public acert_validator_t interface. + */ + acert_validator_t public; +}; + +/** + * Check if an AC can be trusted + */ +static bool verify(private_acert_validator_t *this, certificate_t *ac) +{ + certificate_t *issuer; + enumerator_t *enumerator; + bool verified = FALSE; + + if (!ac->get_validity(ac, NULL, NULL, NULL)) + { + return FALSE; + } + DBG1(DBG_CFG, "verifying attribute certificate issued by \"%Y\"", + ac->get_issuer(ac)); + enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr, KEY_ANY, + ac->get_issuer(ac), TRUE); + while (enumerator->enumerate(enumerator, &issuer, NULL)) + { + if (issuer->get_validity(issuer, NULL, NULL, NULL)) + { + if (lib->credmgr->issued_by(lib->credmgr, ac, issuer, NULL)) + { + verified = TRUE; + break; + } + } + } + enumerator->destroy(enumerator); + + return verified; +} + +/** + * Apply AC group membership to auth config + */ +static void apply(private_acert_validator_t *this, ac_t *ac, auth_cfg_t *auth) +{ + enumerator_t *enumerator; + ac_group_type_t type; + chunk_t chunk; + + enumerator = ac->create_group_enumerator(ac); + while (enumerator->enumerate(enumerator, &type, &chunk)) + { + if (type == AC_GROUP_TYPE_STRING) + { + auth->add(auth, AUTH_RULE_GROUP, + identification_create_from_data(chunk)); + } + } + enumerator->destroy(enumerator); +} + +METHOD(cert_validator_t, validate, bool, + private_acert_validator_t *this, certificate_t *subject, + certificate_t *issuer, bool online, u_int pathlen, bool anchor, + auth_cfg_t *auth) +{ + /* for X.509 end entity certs only */ + if (pathlen == 0 && subject->get_type(subject) == CERT_X509) + { + x509_t *x509 = (x509_t*)subject; + enumerator_t *enumerator; + identification_t *id, *serial; + ac_t *ac; + + /* find attribute certificates by serial and issuer. A lookup by + * the holder DN would work as well, but RFC 5755 recommends the use + * of baseCertificateID. */ + serial = identification_create_from_encoding(ID_KEY_ID, + x509->get_serial(x509)); + enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, + CERT_X509_AC, KEY_ANY, serial, FALSE); + while (enumerator->enumerate(enumerator, &ac)) + { + id = ac->get_holderIssuer(ac); + if (id && id->equals(id, subject->get_issuer(subject))) + { + if (verify(this, &ac->certificate)) + { + apply(this, ac, auth); + } + } + } + enumerator->destroy(enumerator); + serial->destroy(serial); + } + return TRUE; +} + +METHOD(acert_validator_t, destroy, void, + private_acert_validator_t *this) +{ + free(this); +} + +/** + * See header + */ +acert_validator_t *acert_validator_create() +{ + private_acert_validator_t *this; + + INIT(this, + .public = { + .validator.validate = _validate, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libstrongswan/plugins/acert/acert_validator.h b/src/libstrongswan/plugins/acert/acert_validator.h new file mode 100644 index 000000000..507776f18 --- /dev/null +++ b/src/libstrongswan/plugins/acert/acert_validator.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014 Martin Willi + * Copyright (C) 2014 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 . + * + * 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 acert_validator acert_validator + * @{ @ingroup acert + */ + +#ifndef ACERT_VALIDATOR_H_ +#define ACERT_VALIDATOR_H_ + +#include + +typedef struct acert_validator_t acert_validator_t; + +/** + * Attribute certificate group membership checking + */ +struct acert_validator_t { + + /** + * Implements cert_validator_t interface. + */ + cert_validator_t validator; + + /** + * Destroy a acert_validator_t. + */ + void (*destroy)(acert_validator_t *this); +}; + +/** + * Create a acert_validator instance. + */ +acert_validator_t *acert_validator_create(); + +#endif /** ACERT_VALIDATOR_H_ @}*/ diff --git a/src/libstrongswan/plugins/pem/pem_encoder.c b/src/libstrongswan/plugins/pem/pem_encoder.c index 9c8237e4d..df4b77cc3 100644 --- a/src/libstrongswan/plugins/pem/pem_encoder.c +++ b/src/libstrongswan/plugins/pem/pem_encoder.c @@ -106,6 +106,12 @@ bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding, label = "CERTIFICATE REQUEST"; break; } + if (cred_encoding_args(args, CRED_PART_X509_AC_ASN1_DER, + &asn1, CRED_PART_END)) + { + label = "ATTRIBUTE CERTIFICATE"; + break; + } default: return FALSE; } @@ -154,4 +160,3 @@ bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding, encoding->len = pos - encoding->ptr; return TRUE; } - diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c index 7d83e48ea..30b871d42 100644 --- a/src/libstrongswan/plugins/x509/x509_ac.c +++ b/src/libstrongswan/plugins/x509/x509_ac.c @@ -29,7 +29,6 @@ #include #include #include -#include #include extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob, @@ -75,7 +74,7 @@ struct private_x509_ac_t { /** * Serial number of the holder certificate */ - chunk_t holderSerial; + identification_t *holderSerial; /** * ID representing the holder @@ -98,14 +97,9 @@ struct private_x509_ac_t { time_t notAfter; /** - * List of charging attributes + * List of group attributes, as group_t */ - ietf_attributes_t *charging; - - /** - * List of groub attributes - */ - ietf_attributes_t *groups; + linked_list_t *groups; /** * Authority Key Identifier @@ -153,6 +147,25 @@ struct private_x509_ac_t { refcount_t ref; }; +/** + * Group definition, an IETF attribute + */ +typedef struct { + /** Attribute type */ + ac_group_type_t type; + /* attribute value */ + chunk_t value; +} group_t; + +/** + * Clean up a group entry + */ +static void group_destroy(group_t *group) +{ + free(group->value.ptr); + free(group); +} + static chunk_t ASN1_noRevAvail_ext = chunk_from_chars( 0x30, 0x09, 0x06, 0x03, @@ -169,42 +182,41 @@ extern void x509_parse_generalNames(chunk_t blob, int level0, bool implicit, /** * parses a directoryName */ -static bool parse_directoryName(chunk_t blob, int level, bool implicit, identification_t **name) +static bool parse_directoryName(chunk_t blob, int level, bool implicit, + identification_t **name) { - bool has_directoryName; - linked_list_t *list = linked_list_create(); + identification_t *directoryName; + enumerator_t *enumerator; + bool first = TRUE; + linked_list_t *list; + list = linked_list_create(); x509_parse_generalNames(blob, level, implicit, list); - has_directoryName = list->get_count(list) > 0; - if (has_directoryName) + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &directoryName)) { - enumerator_t *enumerator = list->create_enumerator(list); - identification_t *directoryName; - bool first = TRUE; - - while (enumerator->enumerate(enumerator, (void**)&directoryName)) + if (first) { - if (first) - { - *name = directoryName; - first = FALSE; - } - else - { - DBG1(DBG_ASN, "more than one directory name - first selected"); - directoryName->destroy(directoryName); - } + *name = directoryName; + first = FALSE; + } + else + { + DBG1(DBG_ASN, "more than one directory name - first selected"); + directoryName->destroy(directoryName); + break; } - enumerator->destroy(enumerator); } - else + enumerator->destroy(enumerator); + list->destroy(list); + + if (first) { DBG1(DBG_ASN, "no directoryName found"); + return FALSE; } - - list->destroy(list); - return has_directoryName; + return TRUE; } /** @@ -243,6 +255,74 @@ static void parse_roleSyntax(chunk_t blob, int level0) parser->destroy(parser); } +/** + * 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 */ + { 0, "exit", ASN1_EOC, ASN1_EXIT } +}; +#define IETF_ATTR_OCTETS 4 +#define IETF_ATTR_OID 6 +#define IETF_ATTR_STRING 8 + +/** + * Parse group memberships, IETF attributes + */ +static bool parse_groups(private_x509_ac_t *this, chunk_t encoded, int level0) +{ + ac_group_type_t type; + group_t *group; + asn1_parser_t *parser; + chunk_t object; + int objectID; + bool success; + + parser = asn1_parser_create(ietfAttrSyntaxObjects, encoded); + parser->set_top_level(parser, level0); + while (parser->iterate(parser, &objectID, &object)) + { + switch (objectID) + { + case IETF_ATTR_OCTETS: + type = AC_GROUP_TYPE_OCTETS; + break; + case IETF_ATTR_OID: + type = AC_GROUP_TYPE_OID; + break; + case IETF_ATTR_STRING: + type = AC_GROUP_TYPE_STRING; + break; + default: + continue; + } + INIT(group, + .type = type, + .value = chunk_clone(object), + ); + this->groups->insert_last(this->groups, group); + } + success = parser->success(parser); + parser->destroy(parser); + + return success; +} + /** * ASN.1 definition of an X509 attribute certificate */ @@ -250,57 +330,57 @@ 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 | + { 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 */ + { 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 | + { 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 | + { 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 | + { 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 */ + { 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 | + { 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 */ + { 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 */ + { 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 */ @@ -368,22 +448,26 @@ static bool parse_certificate(private_x509_ac_t *this) } break; case AC_OBJ_HOLDER_ISSUER: - if (!parse_directoryName(object, level, FALSE, &this->holderIssuer)) + if (!parse_directoryName(object, level, FALSE, + &this->holderIssuer)) { goto end; } break; case AC_OBJ_HOLDER_SERIAL: - this->holderSerial = object; + this->holderSerial = identification_create_from_encoding( + ID_KEY_ID, object); break; case AC_OBJ_ENTITY_NAME: - if (!parse_directoryName(object, level, TRUE, &this->entityName)) + if (!parse_directoryName(object, level, TRUE, + &this->entityName)) { goto end; } break; case AC_OBJ_ISSUER_NAME: - if (!parse_directoryName(object, level, FALSE, &this->issuerName)) + if (!parse_directoryName(object, level, FALSE, + &this->issuerName)) { goto end; } @@ -414,13 +498,14 @@ static bool parse_certificate(private_x509_ac_t *this) DBG2(DBG_ASN, " need to parse accessIdentity"); break; case OID_CHARGING_IDENTITY: - DBG2(DBG_ASN, "-- > --"); - this->charging = ietf_attributes_create_from_encoding(object); - DBG2(DBG_ASN, "-- < --"); + DBG2(DBG_ASN, " need to parse chargingIdentity"); break; case OID_GROUP: DBG2(DBG_ASN, "-- > --"); - this->groups = ietf_attributes_create_from_encoding(object); + if (!parse_groups(this, object, level)) + { + goto end; + } DBG2(DBG_ASN, "-- < --"); break; case OID_ROLE: @@ -446,8 +531,9 @@ static bool parse_certificate(private_x509_ac_t *this) DBG2(DBG_ASN, " need to parse crlDistributionPoints"); break; case OID_AUTHORITY_KEY_ID: - this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object, - level, &this->authKeySerialNumber); + this->authKeyIdentifier = + x509_parse_authorityKeyIdentifier(object, + level, &this->authKeySerialNumber); break; case OID_TARGET_INFORMATION: DBG2(DBG_ASN, " need to parse targetInformation"); @@ -490,7 +576,7 @@ end: static chunk_t build_directoryName(asn1_t tag, chunk_t name) { return asn1_wrap(tag, "m", - asn1_simple_object(ASN1_CONTEXT_C_4, name)); + asn1_simple_object(ASN1_CONTEXT_C_4, name)); } /** @@ -499,14 +585,15 @@ static chunk_t build_directoryName(asn1_t tag, chunk_t name) static chunk_t build_holder(private_x509_ac_t *this) { x509_t* x509 = (x509_t*)this->holderCert; - identification_t *issuer = this->holderCert->get_issuer(this->holderCert); - identification_t *subject = this->holderCert->get_subject(this->holderCert); + identification_t *issuer, *subject; + + issuer = this->holderCert->get_issuer(this->holderCert); + subject = this->holderCert->get_subject(this->holderCert); return asn1_wrap(ASN1_SEQUENCE, "mm", asn1_wrap(ASN1_CONTEXT_C_0, "mm", build_directoryName(ASN1_SEQUENCE, issuer->get_encoding(issuer)), - asn1_simple_object(ASN1_INTEGER, x509->get_serial(x509)) - ), + asn1_simple_object(ASN1_INTEGER, x509->get_serial(x509))), build_directoryName(ASN1_CONTEXT_C_1, subject->get_encoding(subject))); } @@ -515,10 +602,12 @@ static chunk_t build_holder(private_x509_ac_t *this) */ static chunk_t build_v2_form(private_x509_ac_t *this) { - identification_t *subject = this->signerCert->get_subject(this->signerCert); + identification_t *subject; + subject = this->signerCert->get_subject(this->signerCert); return asn1_wrap(ASN1_CONTEXT_C_0, "m", - build_directoryName(ASN1_SEQUENCE, subject->get_encoding(subject))); + build_directoryName(ASN1_SEQUENCE, + subject->get_encoding(subject))); } /** @@ -531,7 +620,6 @@ static chunk_t build_attr_cert_validity(private_x509_ac_t *this) asn1_from_time(&this->notAfter, ASN1_GENERALIZEDTIME)); } - /** * build attribute type */ @@ -547,8 +635,55 @@ static chunk_t build_attribute_type(int type, chunk_t content) */ static chunk_t build_attributes(private_x509_ac_t *this) { + enumerator_t *enumerator; + group_t *group; + chunk_t values; + size_t size = 0, len; + u_char *pos; + + /* precalculate the total size of all values */ + enumerator = this->groups->create_enumerator(this->groups); + while (enumerator->enumerate(enumerator, &group)) + { + len = group->value.len; + size += 1 + (len > 0) + (len >= 128) + + (len >= 256) + (len >= 65536) + len; + } + enumerator->destroy(enumerator); + + pos = asn1_build_object(&values, ASN1_SEQUENCE, size); + + enumerator = this->groups->create_enumerator(this->groups); + while (enumerator->enumerate(enumerator, &group)) + { + chunk_t attr; + asn1_t type; + + switch (group->type) + { + case AC_GROUP_TYPE_OCTETS: + type = ASN1_OCTET_STRING; + break; + case AC_GROUP_TYPE_STRING: + type = ASN1_UTF8STRING; + break; + case AC_GROUP_TYPE_OID: + type = ASN1_OID; + break; + default: + continue; + } + attr = asn1_simple_object(type, group->value); + + memcpy(pos, attr.ptr, attr.len); + pos += attr.len; + free(attr.ptr); + } + enumerator->destroy(enumerator); + return asn1_wrap(ASN1_SEQUENCE, "m", - build_attribute_type(OID_GROUP, this->groups->get_encoding(this->groups))); + build_attribute_type(OID_GROUP, + asn1_wrap(ASN1_SEQUENCE, "m", values))); } /** @@ -621,14 +756,11 @@ static chunk_t build_attr_cert_info(private_x509_ac_t *this) */ static chunk_t build_ac(private_x509_ac_t *this) { - chunk_t signatureValue; - chunk_t attributeCertificateInfo; + chunk_t signatureValue, attributeCertificateInfo; attributeCertificateInfo = build_attr_cert_info(this); - this->signerKey->sign(this->signerKey, SIGN_RSA_EMSA_PKCS1_SHA1, attributeCertificateInfo, &signatureValue); - return asn1_wrap(ASN1_SEQUENCE, "mmm", attributeCertificateInfo, asn1_algorithmIdentifier(OID_SHA1_WITH_RSA), @@ -644,7 +776,11 @@ METHOD(ac_t, get_serial, chunk_t, METHOD(ac_t, get_holderSerial, chunk_t, private_x509_ac_t *this) { - return this->holderSerial; + if (this->holderSerial) + { + return this->holderSerial->get_encoding(this->holderSerial); + } + return chunk_empty; } METHOD(ac_t, get_holderIssuer, identification_t*, @@ -659,10 +795,28 @@ METHOD(ac_t, get_authKeyIdentifier, chunk_t, return this->authKeyIdentifier; } -METHOD(ac_t, get_groups, ietf_attributes_t*, +/** + * Filter function for attribute enumeration + */ +static bool attr_filter(void *null, group_t **in, ac_group_type_t *type, + void *in2, chunk_t *out) +{ + if ((*in)->type == AC_GROUP_TYPE_STRING && + !chunk_printable((*in)->value, NULL, 0)) + { /* skip non-printable strings */ + return FALSE; + } + *type = (*in)->type; + *out = (*in)->value; + return TRUE; +} + +METHOD(ac_t, create_group_enumerator, enumerator_t*, private_x509_ac_t *this) { - return this->groups ? this->groups->get_ref(this->groups) : NULL; + return enumerator_create_filter( + this->groups->create_enumerator(this->groups), + (void*)attr_filter, NULL, NULL); } METHOD(certificate_t, get_type, certificate_type_t, @@ -674,7 +828,11 @@ METHOD(certificate_t, get_type, certificate_type_t, METHOD(certificate_t, get_subject, identification_t*, private_x509_ac_t *this) { - return this->entityName; + if (this->entityName) + { + return this->entityName; + } + return this->holderSerial; } METHOD(certificate_t, get_issuer, identification_t*, @@ -686,13 +844,24 @@ METHOD(certificate_t, get_issuer, identification_t*, METHOD(certificate_t, has_subject, id_match_t, private_x509_ac_t *this, identification_t *subject) { - return ID_MATCH_NONE; + id_match_t entity = ID_MATCH_NONE, serial = ID_MATCH_NONE; + + if (this->entityName) + { + entity = this->entityName->matches(this->entityName, subject); + } + if (this->holderSerial) + { + serial = this->holderSerial->matches(this->holderSerial, subject); + } + return max(entity, serial); } METHOD(certificate_t, has_issuer, id_match_t, private_x509_ac_t *this, identification_t *issuer) { - if (issuer->get_type(issuer) == ID_KEY_ID && this->authKeyIdentifier.ptr && + if (issuer->get_type(issuer) == ID_KEY_ID && + this->authKeyIdentifier.ptr && chunk_equals(this->authKeyIdentifier, issuer->get_encoding(issuer))) { return ID_MATCH_PERFECT; @@ -808,9 +977,10 @@ METHOD(certificate_t, equals, bool, { return TRUE; } - if (other->equals == (void*)equals) + if (other->equals == _equals) { /* skip allocation if we have the same implementation */ - return chunk_equals(this->encoding, ((private_x509_ac_t*)other)->encoding); + return chunk_equals(this->encoding, + ((private_x509_ac_t*)other)->encoding); } if (!other->get_encoding(other, CERT_ASN1_DER, &encoding)) { @@ -827,13 +997,13 @@ METHOD(certificate_t, destroy, void, if (ref_put(&this->ref)) { DESTROY_IF(this->holderIssuer); + DESTROY_IF(this->holderSerial); DESTROY_IF(this->entityName); DESTROY_IF(this->issuerName); DESTROY_IF(this->holderCert); DESTROY_IF(this->signerCert); DESTROY_IF(this->signerKey); - DESTROY_IF(this->charging); - DESTROY_IF(this->groups); + this->groups->destroy_function(this->groups, (void*)group_destroy); free(this->serialNumber.ptr); free(this->authKeyIdentifier.ptr); free(this->encoding.ptr); @@ -869,9 +1039,10 @@ static private_x509_ac_t *create_empty(void) .get_holderSerial = _get_holderSerial, .get_holderIssuer = _get_holderIssuer, .get_authKeyIdentifier = _get_authKeyIdentifier, - .get_groups = _get_groups, + .create_group_enumerator = _create_group_enumerator, }, }, + .groups = linked_list_create(), .ref = 1, ); @@ -913,6 +1084,27 @@ x509_ac_t *x509_ac_load(certificate_type_t type, va_list args) return NULL; } +/** + * Add groups from a list into AC group memberships + */ +static void add_groups_from_list(private_x509_ac_t *this, linked_list_t *list) +{ + enumerator_t *enumerator; + group_t *group; + char *name; + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &name)) + { + INIT(group, + .type = AC_GROUP_TYPE_STRING, + .value = chunk_clone(chunk_from_str(name)), + ); + this->groups->insert_last(this->groups, group); + } + enumerator->destroy(enumerator); +} + /** * See header. */ @@ -934,8 +1126,8 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) case BUILD_SERIAL: ac->serialNumber = chunk_clone(va_arg(args, chunk_t)); continue; - case BUILD_IETF_GROUP_ATTR: - ac->groups = ietf_attributes_create_from_string(va_arg(args, char*)); + case BUILD_AC_GROUP_STRINGS: + add_groups_from_list(ac, va_arg(args, linked_list_t*)); continue; case BUILD_CERT: ac->holderCert = va_arg(args, certificate_t*); @@ -968,4 +1160,3 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) destroy(ac); return NULL; } - diff --git a/src/openac/.gitignore b/src/openac/.gitignore deleted file mode 100644 index 9aa85775f..000000000 --- a/src/openac/.gitignore +++ /dev/null @@ -1 +0,0 @@ -openac diff --git a/src/openac/Makefile.am b/src/openac/Makefile.am deleted file mode 100644 index 78a466bd6..000000000 --- a/src/openac/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -ipsec_PROGRAMS = openac -openac_SOURCES = openac.c -dist_man_MANS = openac.8 - -AM_CPPFLAGS = \ - -I$(top_srcdir)/src/libstrongswan \ - -DIPSEC_CONFDIR=\"${sysconfdir}\" \ - -DPLUGINS=\""${openac_plugins}\"" - -openac_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -openac.o : $(top_builddir)/config.status diff --git a/src/openac/openac.8 b/src/openac/openac.8 deleted file mode 100644 index ed1b8ed6c..000000000 --- a/src/openac/openac.8 +++ /dev/null @@ -1,165 +0,0 @@ -.TH IPSEC_OPENAC 8 "22 September 2007" -.SH NAME -ipsec openac \- Generation of X.509 attribute certificates -.SH SYNOPSIS -.B ipsec -.B openac -[ -.B \-\-help -] [ -.B \-\-version -] [ -.B \-\-optionsfrom -\fIfilename\fP -] -.br -\ \ \ [ -.B \-\-quiet -] [ -.B \-\-debug -\fIlevel\fP -] -.br -\ \ \ [ -.B \-\-days -\fIdays\fP -] [ -.B \-\-hours -\fIhours\fP -] -.br -\ \ \ [ -.B \-\-startdate -\fIYYYYMMDDHHMMSSZ\fP -] [ -.B \-\-stopdate -\fIYYYYMMDDHHMMSSZ\fP -] -.br -.B \ \ \ \-\-cert -\fIcertfile\fP -.B \-\-key -\fIkeyfile\fP -[ -.B \-\-password -\fIpassword\fP -] -.br -.B \ \ \ \-\-usercert -\fIcertfile\fP -.B \-\-groups -\fIattr1,attr2,...\fP -.B \-\-out -\fIfilename\fP -.SH DESCRIPTION -.BR openac -is intended to be used by an Authorization Authority (AA) to generate and sign -X.509 attribute certificates. Currently only the inclusion of one ore several group -attributes is supported. An attribute certificate is linked to a holder by -including the issuer and serial number of the holder's X.509 certificate. -.SH OPTIONS -.TP -\fB\-\-help\fP -display the usage message. -.TP -\fB\-\-version\fP -display the version of \fBopenac\fP. -.TP -\fB\-\-optionsfrom\fP\ \fIfilename\fP -adds the contents of the file to the argument list. -If \fIfilename\fP is a relative path then the file is searched in the directory -\fI/etc/openac\fP. -.TP -\fB\-\-quiet\fP -By default \fBopenac\fP logs all control output both to syslog and stderr. -With the \fB\-\-quiet\fP option no output is written to stderr. -.TP -\fB\-\-days\fP\ \fIdays\fP -Validity of the X.509 attribute certificate in days. If neiter the \fB\-\-days\fP\ nor -the \fB\-\-hours\fP\ option is specified then a default validity interval of 1 day is assumed. -The \fB\-\-days\fP\ option can be combined with the \fB\-\-hours\fP\ option. -.TP -\fB\-\-hours\fP\ \fIhours\fP -Validity of the X.509 attribute certificate in hours. If neiter the \fB\-\-hours\fP\ nor -the \fB\-\-days\fP\ option is specified then a default validity interval of 24 hours is assumed. -The \fB\-\-hours\fP\ option can be combined with the \fB\-\-days\fP\ option. -.TP -\fB\-\-startdate\fP\ \fIYYYYMMDDHHMMSSZ\fP -defines the \fBnotBefore\fP date when the X.509 attribute certificate becomes valid. -The date \fIYYYYMMDDHHMMSS\fP must be specified in UTC (\fIZ\fPulu time). -If the \fB\-\-startdate\fP option is not specified then the current date is taken as a default. - -.TP -\fB\-\-stopdate\fP\ \fIYYYYMMDDHHMMSSZ\fP -defines the \fBnotAfter\fP date when the X.509 attribute certificate will expire. -The date \fIYYYYMMDDHHMMSS\fP must be specified in UTC (\fIZ\fPulu time). -If the \fB\-\-stopdate\fP option is not specified then the default \fBnotAfter\fP value is computed -by adding the validity interval specified by the \fB\-\-days\fP\ and/or \fB\-\-days\fP\ options -to the \fBnotBefore\fP date. -.TP -\fB\-\-cert\fP\ \fIcertfile\fP -specifies the file containing the X.509 certificate of the Authorization Authority. -The certificate is stored either in PEM or DER format. -.TP -\fB\-\-key\fP\ \fIkeyfile\fP -specifies the encrypted file containing the private RSA key of the Authoritzation -Authority. The private key is stored in PKCS#1 format. -.TP -\fB\-\-password\fP\ \fIpassword\fP -specifies the password with which the private RSA keyfile defined by the -\fB\-\-key\fP option has been protected. If the option is missing then the -password is prompted for on the command line. -.TP -\fB\-\-usercert\fP\ \fIcertfile\fP -specifies file containing the X.509 certificate of the user to which the generated attribute -certificate will apply. The certificate file is stored either in PEM or DER format. -.TP -\fB\-\-groups\fP\ \fIattr1,attr2\fP -specifies a comma-separated list of group attributes that will go into the -X.509 attribute certificate. -.TP -\fB\-\-out\fP\ \fIfilename\fP -specifies the file where the generated X.509 attribute certificate will be stored to. -.SS Debugging -.LP -\fBopenac\fP produces a prodigious amount of debugging information. To do so, -it must be compiled with \-DDEBUG. There are several classes of debugging output, -and \fBopenac\fP may be directed to produce a selection of them. All lines of -debugging output are prefixed with ``|\ '' to distinguish them from error messages. -.LP -When \fBopenac\fP is invoked, it may be given arguments to specify -which classes to output. The current options are: -.TP -\fB\-\-debug\fP\ \fIlevel\fP -sets the debug level to 0 (none), 1 (normal), 2 (more), 3 (raw), and 4 (private), -the default level being 1. -.SH EXIT STATUS -.LP -The execution of \fBopenac\fP terminates with one of the following two exit codes: -.TP -0 -means that the attribute certificate was successfully generated and stored. -.TP -1 -means that something went wrong. -.SH FILES -\fI/etc/openac/serial\fP\ \ \ serial number of latest attribute certificate -.SH SEE ALSO -.LP -The X.509 attribute certificates generated with \fBopenac\fP can be used to -enforce group policies defined by \fIipsec.conf\fP(5). Use \fIipsec_auto\fP(8) -to load and list X.509 attribute certificates. -.LP -For more information on X.509 attribute certificates, refer to the following -IETF RFC: -.IP -RFC 3281 An Internet Attribute Certificate Profile for Authorization -.SH HISTORY -The \fBopenac\fP program was originally written by Ariane Seiler and Ueli Galizzi. -The software was recoded by Andreas Steffen using strongSwan's X.509 library and -the ASN.1 code synthesis functions written by Christoph Gysin and Christoph Zwahlen. -All authors were with the Zurich University of Applied Sciences in Winterthur, -Switzerland. -.LP -.SH BUGS -Bugs should be reported to the mailing list. diff --git a/src/openac/openac.c b/src/openac/openac.c deleted file mode 100644 index 8862e9ab0..000000000 --- a/src/openac/openac.c +++ /dev/null @@ -1,551 +0,0 @@ -/** - * @file openac.c - * - * @brief Generation of X.509 attribute certificates. - * - */ - -/* - * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler - * Copyright (C) 2004,2007 Andreas Steffen - * Hochschule fuer Technik Rapperswil, Switzerland - * - * 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 -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define OPENAC_PATH IPSEC_CONFDIR "/openac" -#define OPENAC_SERIAL IPSEC_CONFDIR "/openac/serial" - -#define DEFAULT_VALIDITY 24*3600 /* seconds */ - -/** - * @brief prints the usage of the program to the stderr - */ -static void usage(const char *message) -{ - if (message != NULL && *message != '\0') - { - fprintf(stderr, "%s\n", message); - } - fprintf(stderr, "Usage: openac" - " [--help]" - " [--version]" - " [--optionsfrom ]" - " [--quiet]" - " \\\n\t" - " [--debug ]" - " \\\n\t" - " [--days ]" - " [--hours ]" - " \\\n\t" - " [--startdate ]" - " [--enddate ]" - " \\\n\t" - " --cert " - " --key " - " [--password ]" - " \\\n\t" - " --usercert " - " --groups " - " --out " - "\n" - ); -} - -/** - * read the last serial number from file - */ -static chunk_t read_serial(void) -{ - chunk_t hex, serial = chunk_empty; - char one[] = {0x01}; - FILE *fd; - - fd = fopen(OPENAC_SERIAL, "r"); - if (fd) - { - hex = chunk_alloca(64); - hex.len = fread(hex.ptr, 1, hex.len, fd); - if (hex.len) - { - /* remove any terminating newline character */ - if (hex.ptr[hex.len-1] == '\n') - { - hex.len--; - } - serial = chunk_alloca((hex.len / 2) + (hex.len % 2)); - serial = chunk_from_hex(hex, serial.ptr); - } - fclose(fd); - } - else - { - DBG1(DBG_LIB, " file '%s' does not exist yet - serial number " - "set to 01", OPENAC_SERIAL); - } - if (!serial.len) - { - return chunk_clone(chunk_create(one, 1)); - } - if (chunk_increment(serial)) - { /* overflow, prepend 0x01 */ - return chunk_cat("cc", chunk_create(one, 1), serial); - } - return chunk_clone(serial); -} - -/** - * write back the last serial number to file - */ -static void write_serial(chunk_t serial) -{ - FILE *fd = fopen(OPENAC_SERIAL, "w"); - - if (fd) - { - chunk_t hex_serial; - - DBG1(DBG_LIB, " serial number is %#B", &serial); - hex_serial = chunk_to_hex(serial, NULL, FALSE); - fprintf(fd, "%.*s\n", (int)hex_serial.len, hex_serial.ptr); - fclose(fd); - free(hex_serial.ptr); - } - else - { - DBG1(DBG_LIB, " could not open file '%s' for writing", OPENAC_SERIAL); - } -} - -/** - * global variables accessible by both main() and build.c - */ - -static int debug_level = 1; -static bool stderr_quiet = FALSE; - -/** - * openac dbg function - */ -static void openac_dbg(debug_t group, level_t level, char *fmt, ...) -{ - int priority = LOG_INFO; - char buffer[8192]; - char *current = buffer, *next; - va_list args; - - if (level <= debug_level) - { - if (!stderr_quiet) - { - va_start(args, fmt); - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); - va_end(args); - } - - /* write in memory buffer first */ - va_start(args, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, args); - va_end(args); - - /* do a syslog with every line */ - while (current) - { - next = strchr(current, '\n'); - if (next) - { - *(next++) = '\0'; - } - syslog(priority, "%s\n", current); - current = next; - } - } -} - -/** - * @brief openac main program - * - * @param argc number of arguments - * @param argv pointer to the argument values - */ -int main(int argc, char **argv) -{ - certificate_t *attr_cert = NULL; - certificate_t *userCert = NULL; - certificate_t *signerCert = NULL; - private_key_t *signerKey = NULL; - - time_t notBefore = UNDEFINED_TIME; - time_t notAfter = UNDEFINED_TIME; - time_t validity = 0; - - char *keyfile = NULL; - char *certfile = NULL; - char *usercertfile = NULL; - char *outfile = NULL; - char *groups = ""; - char buf[BUF_LEN]; - - chunk_t passphrase = { buf, 0 }; - chunk_t serial = chunk_empty; - chunk_t attr_chunk = chunk_empty; - - int status = 1; - - /* enable openac debugging hook */ - dbg = openac_dbg; - - passphrase.ptr[0] = '\0'; - - openlog("openac", 0, LOG_AUTHPRIV); - - /* initialize library */ - atexit(library_deinit); - if (!library_init(NULL, "openac")) - { - exit(SS_RC_LIBSTRONGSWAN_INTEGRITY); - } - if (lib->integrity && - !lib->integrity->check_file(lib->integrity, "openac", argv[0])) - { - fprintf(stderr, "integrity check of openac failed\n"); - exit(SS_RC_DAEMON_INTEGRITY); - } - if (!lib->plugins->load(lib->plugins, - lib->settings->get_str(lib->settings, "openac.load", PLUGINS))) - { - exit(SS_RC_INITIALIZATION_FAILED); - } - - /* initialize optionsfrom */ - options_t *options = options_create(); - - /* handle arguments */ - for (;;) - { - static const struct option long_opts[] = { - /* name, has_arg, flag, val */ - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'v' }, - { "optionsfrom", required_argument, NULL, '+' }, - { "quiet", no_argument, NULL, 'q' }, - { "cert", required_argument, NULL, 'c' }, - { "key", required_argument, NULL, 'k' }, - { "password", required_argument, NULL, 'p' }, - { "usercert", required_argument, NULL, 'u' }, - { "groups", required_argument, NULL, 'g' }, - { "days", required_argument, NULL, 'D' }, - { "hours", required_argument, NULL, 'H' }, - { "startdate", required_argument, NULL, 'S' }, - { "enddate", required_argument, NULL, 'E' }, - { "out", required_argument, NULL, 'o' }, - { "debug", required_argument, NULL, 'd' }, - { 0,0,0,0 } - }; - - int c = getopt_long(argc, argv, "hv+:qc:k:p;u:g:D:H:S:E:o:d:", long_opts, NULL); - - /* Note: "breaking" from case terminates loop */ - switch (c) - { - case EOF: /* end of flags */ - break; - - case 0: /* long option already handled */ - continue; - - case ':': /* diagnostic already printed by getopt_long */ - case '?': /* diagnostic already printed by getopt_long */ - case 'h': /* --help */ - usage(NULL); - status = 1; - goto end; - - case 'v': /* --version */ - printf("openac (strongSwan %s)\n", VERSION); - status = 0; - goto end; - - case '+': /* --optionsfrom */ - { - char path[BUF_LEN]; - - if (*optarg == '/') /* absolute pathname */ - { - strncpy(path, optarg, BUF_LEN); - path[BUF_LEN-1] = '\0'; - } - else /* relative pathname */ - { - snprintf(path, BUF_LEN, "%s/%s", OPENAC_PATH, optarg); - } - if (!options->from(options, path, &argc, &argv, optind)) - { - status = 1; - goto end; - } - } - continue; - - case 'q': /* --quiet */ - stderr_quiet = TRUE; - continue; - - case 'c': /* --cert */ - certfile = optarg; - continue; - - case 'k': /* --key */ - keyfile = optarg; - continue; - - case 'p': /* --key */ - if (strlen(optarg) >= BUF_LEN) - { - usage("passphrase too long"); - goto end; - } - strncpy(passphrase.ptr, optarg, BUF_LEN); - passphrase.len = min(strlen(optarg), BUF_LEN); - continue; - - case 'u': /* --usercert */ - usercertfile = optarg; - continue; - - case 'g': /* --groups */ - groups = optarg; - continue; - - case 'D': /* --days */ - if (optarg == NULL || !isdigit(optarg[0])) - { - usage("missing number of days"); - goto end; - } - else - { - char *endptr; - long days = strtol(optarg, &endptr, 0); - - if (*endptr != '\0' || endptr == optarg || days <= 0) - { - usage(" must be a positive number"); - goto end; - } - validity += 24*3600*days; - } - continue; - - case 'H': /* --hours */ - if (optarg == NULL || !isdigit(optarg[0])) - { - usage("missing number of hours"); - goto end; - } - else - { - char *endptr; - long hours = strtol(optarg, &endptr, 0); - - if (*endptr != '\0' || endptr == optarg || hours <= 0) - { - usage(" must be a positive number"); - goto end; - } - validity += 3600*hours; - } - continue; - - case 'S': /* --startdate */ - if (optarg == NULL || strlen(optarg) != 15 || optarg[14] != 'Z') - { - usage("date format must be YYYYMMDDHHMMSSZ"); - goto end; - } - else - { - chunk_t date = { optarg, 15 }; - - notBefore = asn1_to_time(&date, ASN1_GENERALIZEDTIME); - } - continue; - - case 'E': /* --enddate */ - if (optarg == NULL || strlen(optarg) != 15 || optarg[14] != 'Z') - { - usage("date format must be YYYYMMDDHHMMSSZ"); - goto end; - } - else - { - chunk_t date = { optarg, 15 }; - notAfter = asn1_to_time(&date, ASN1_GENERALIZEDTIME); - } - continue; - - case 'o': /* --out */ - outfile = optarg; - continue; - - case 'd': /* --debug */ - debug_level = atoi(optarg); - continue; - - default: - usage(""); - status = 0; - goto end; - } - /* break from loop */ - break; - } - - if (optind != argc) - { - usage("unexpected argument"); - goto end; - } - - DBG1(DBG_LIB, "starting openac (strongSwan Version %s)", VERSION); - - /* load the signer's RSA private key */ - if (keyfile != NULL) - { - mem_cred_t *mem; - shared_key_t *shared; - - mem = mem_cred_create(); - lib->credmgr->add_set(lib->credmgr, &mem->set); - shared = shared_key_create(SHARED_PRIVATE_KEY_PASS, - chunk_clone(passphrase)); - mem->add_shared(mem, shared, NULL); - signerKey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA, - BUILD_FROM_FILE, keyfile, - BUILD_END); - lib->credmgr->remove_set(lib->credmgr, &mem->set); - mem->destroy(mem); - if (signerKey == NULL) - { - goto end; - } - DBG1(DBG_LIB, " loaded private key file '%s'", keyfile); - } - - /* load the signer's X.509 certificate */ - if (certfile != NULL) - { - signerCert = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509, - BUILD_FROM_FILE, certfile, - BUILD_END); - if (signerCert == NULL) - { - goto end; - } - } - - /* load the users's X.509 certificate */ - if (usercertfile != NULL) - { - userCert = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509, - BUILD_FROM_FILE, usercertfile, - BUILD_END); - if (userCert == NULL) - { - goto end; - } - } - - /* compute validity interval */ - validity = (validity)? validity : DEFAULT_VALIDITY; - notBefore = (notBefore == UNDEFINED_TIME) ? time(NULL) : notBefore; - notAfter = (notAfter == UNDEFINED_TIME) ? time(NULL) + validity : notAfter; - - /* build and parse attribute certificate */ - if (userCert != NULL && signerCert != NULL && signerKey != NULL && - outfile != NULL) - { - /* read the serial number and increment it by one */ - serial = read_serial(); - - attr_cert = lib->creds->create(lib->creds, - CRED_CERTIFICATE, CERT_X509_AC, - BUILD_CERT, userCert, - BUILD_NOT_BEFORE_TIME, notBefore, - BUILD_NOT_AFTER_TIME, notAfter, - BUILD_SERIAL, serial, - BUILD_IETF_GROUP_ATTR, groups, - BUILD_SIGNING_CERT, signerCert, - BUILD_SIGNING_KEY, signerKey, - BUILD_END); - if (!attr_cert) - { - goto end; - } - - /* write the attribute certificate to file */ - if (attr_cert->get_encoding(attr_cert, CERT_ASN1_DER, &attr_chunk)) - { - if (chunk_write(attr_chunk, outfile, 0022, TRUE)) - { - DBG1(DBG_APP, " written attribute cert file '%s' (%d bytes)", - outfile, attr_chunk.len); - write_serial(serial); - status = 0; - } - else - { - DBG1(DBG_APP, " writing attribute cert file '%s' failed: %s", - outfile, strerror(errno)); - } - } - } - else - { - usage("some of the mandatory parameters --usercert --cert --key --out " - "are missing"); - } - -end: - /* delete all dynamically allocated objects */ - DESTROY_IF(signerKey); - DESTROY_IF(signerCert); - DESTROY_IF(userCert); - DESTROY_IF(attr_cert); - free(attr_chunk.ptr); - free(serial.ptr); - closelog(); - dbg = dbg_default; - options->destroy(options); - exit(status); -} diff --git a/src/pki/Makefile.am b/src/pki/Makefile.am index efbed9b2b..266802cf7 100644 --- a/src/pki/Makefile.am +++ b/src/pki/Makefile.am @@ -11,6 +11,7 @@ pki_SOURCES = pki.c pki.h command.c command.h \ commands/self.c \ commands/print.c \ commands/signcrl.c \ + commands/acert.c \ commands/pkcs7.c \ commands/verify.c diff --git a/src/pki/command.h b/src/pki/command.h index 737f4658d..9cf036bf2 100644 --- a/src/pki/command.h +++ b/src/pki/command.h @@ -24,12 +24,12 @@ /** * Maximum number of commands (+1). */ -#define MAX_COMMANDS 11 +#define MAX_COMMANDS 12 /** * Maximum number of options in a command (+3) */ -#define MAX_OPTIONS 32 +#define MAX_OPTIONS 36 /** * Maximum number of usage summary lines (+1) diff --git a/src/pki/commands/acert.c b/src/pki/commands/acert.c new file mode 100644 index 000000000..d49365db5 --- /dev/null +++ b/src/pki/commands/acert.c @@ -0,0 +1,292 @@ +/* + * 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 . + * + * 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 "pki.h" + +#include +#include +#include +#include +#include +#include + +/** + * Issue an attribute certificate + */ +static int acert() +{ + cred_encoding_type_t form = CERT_ASN1_DER; + hash_algorithm_t digest = HASH_SHA1; + certificate_t *ac = NULL, *cert = NULL, *issuer =NULL; + private_key_t *private = NULL; + public_key_t *public = NULL; + char *file = NULL, *hex = NULL, *issuercert = NULL, *issuerkey = NULL; + char *error = NULL, *keyid = NULL; + linked_list_t *groups; + chunk_t serial = chunk_empty, encoding = chunk_empty; + time_t not_before, not_after, lifetime = 24 * 60 * 60; + char *datenb = NULL, *datena = NULL, *dateform = NULL; + rng_t *rng; + char *arg; + + groups = linked_list_create(); + + while (TRUE) + { + switch (command_getopt(&arg)) + { + case 'h': + goto usage; + case 'g': + digest = enum_from_name(hash_algorithm_short_names, arg); + if (digest == -1) + { + error = "invalid --digest type"; + goto usage; + } + continue; + case 'i': + file = arg; + continue; + case 'm': + groups->insert_last(groups, arg); + continue; + case 'c': + issuercert = arg; + continue; + case 'k': + issuerkey = arg; + continue; + case 'x': + keyid = arg; + continue; + case 'l': + lifetime = atoi(arg) * 60 * 60; + if (!lifetime) + { + error = "invalid --lifetime value"; + goto usage; + } + continue; + case 'D': + dateform = arg; + continue; + case 'F': + datenb = arg; + continue; + case 'T': + datena = arg; + continue; + case 's': + hex = arg; + continue; + case 'f': + if (!get_form(arg, &form, CRED_CERTIFICATE)) + { + error = "invalid output format"; + goto usage; + } + continue; + case EOF: + break; + default: + error = "invalid --acert option"; + goto usage; + } + break; + } + + if (!calculate_lifetime(dateform, datenb, datena, lifetime, + ¬_before, ¬_after)) + { + error = "invalid --not-before/after datetime"; + goto usage; + } + + if (!issuercert) + { + error = "--issuercert is required"; + goto usage; + } + if (!issuerkey && !keyid) + { + error = "--issuerkey or --issuerkeyid is required"; + goto usage; + } + + issuer = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, issuercert, BUILD_END); + if (!issuer) + { + error = "parsing issuer certificate failed"; + goto end; + } + public = issuer->get_public_key(issuer); + if (!public) + { + error = "extracting issuer certificate public key failed"; + goto end; + } + if (issuerkey) + { + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, + public->get_type(public), + BUILD_FROM_FILE, issuerkey, BUILD_END); + } + else + { + chunk_t chunk; + + chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL); + private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY, + BUILD_PKCS11_KEYID, chunk, BUILD_END); + free(chunk.ptr); + } + if (!private) + { + error = "loading issuer private key failed"; + goto end; + } + if (!private->belongs_to(private, public)) + { + error = "issuer private key does not match issuer certificate"; + goto end; + } + + if (hex) + { + serial = chunk_from_hex(chunk_create(hex, strlen(hex)), NULL); + } + else + { + rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK); + if (!rng) + { + error = "no random number generator found"; + goto end; + } + if (!rng_allocate_bytes_not_zero(rng, 8, &serial, FALSE)) + { + error = "failed to generate serial number"; + rng->destroy(rng); + goto end; + } + serial.ptr[0] &= 0x7F; + rng->destroy(rng); + } + + if (file) + { + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_FROM_FILE, file, BUILD_END); + } + else + { + if (!chunk_from_fd(0, &encoding)) + { + fprintf(stderr, "%s: ", strerror(errno)); + error = "reading public key failed"; + goto end; + } + cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, + BUILD_BLOB, encoding, BUILD_END); + chunk_free(&encoding); + } + if (!cert) + { + error = "parsing user certificate failed"; + goto end; + } + + ac = lib->creds->create(lib->creds, + CRED_CERTIFICATE, CERT_X509_AC, + BUILD_CERT, cert, + BUILD_NOT_BEFORE_TIME, not_before, + BUILD_NOT_AFTER_TIME, not_after, + BUILD_SERIAL, serial, + BUILD_AC_GROUP_STRINGS, groups, + BUILD_SIGNING_CERT, issuer, + BUILD_SIGNING_KEY, private, + BUILD_END); + if (!ac) + { + error = "generating attribute certificate failed"; + goto end; + } + if (!ac->get_encoding(ac, form, &encoding)) + { + error = "encoding attribute certificate failed"; + goto end; + } + if (fwrite(encoding.ptr, encoding.len, 1, stdout) != 1) + { + error = "writing attribute certificate key failed"; + goto end; + } + +end: + DESTROY_IF(ac); + DESTROY_IF(cert); + DESTROY_IF(issuer); + DESTROY_IF(public); + DESTROY_IF(private); + groups->destroy(groups); + free(encoding.ptr); + free(serial.ptr); + + if (error) + { + fprintf(stderr, "%s\n", error); + return 1; + } + return 0; + +usage: + groups->destroy(groups); + return command_usage(error); +} + +/** + * Register the command. + */ +static void __attribute__ ((constructor))reg() +{ + command_register((command_t) { + acert, 'z', "acert", + "issue an attribute certificate", + {"[--in file] [--group name]* --issuerkey file|--issuerkeyid hex", + " --issuercert file [--serial hex] [--lifetime hours]", + " [--not-before datetime] [--not-after datetime] [--dateform form]", + "[--digest md5|sha1|sha224|sha256|sha384|sha512] [--outform der|pem]"}, + { + {"help", 'h', 0, "show usage information"}, + {"in", 'i', 1, "holder certificate, default: stdin"}, + {"group", 'm', 1, "group membership string to include"}, + {"issuercert", 'c', 1, "issuer certificate file"}, + {"issuerkey", 'k', 1, "issuer private key file"}, + {"issuerkeyid", 'x', 1, "keyid on smartcard of issuer private key"}, + {"serial", 's', 1, "serial number in hex, default: random"}, + {"lifetime", 'l', 1, "hours the acert is valid, default: 24"}, + {"not-before", 'F', 1, "date/time the validity of the AC starts"}, + {"not-after", 'T', 1, "date/time the validity of the AC ends"}, + {"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"}, + {"digest", 'g', 1, "digest for signature creation, default: sha1"}, + {"outform", 'f', 1, "encoding of generated cert, default: der"}, + } + }); +} diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c index d5c33b89f..8d38e2c5a 100644 --- a/src/pki/commands/issue.c +++ b/src/pki/commands/issue.c @@ -72,8 +72,8 @@ static int issue() int inhibit_mapping = X509_NO_CONSTRAINT, require_explicit = X509_NO_CONSTRAINT; chunk_t serial = chunk_empty; chunk_t encoding = chunk_empty; - time_t lifetime = 1095; - time_t not_before, not_after; + time_t not_before, not_after, lifetime = 1095 * 24 * 60 * 60; + char *datenb = NULL, *datena = NULL, *dateform = NULL; x509_flag_t flags = 0; x509_t *x509; x509_cdp_t *cdp = NULL; @@ -132,13 +132,22 @@ static int issue() san->insert_last(san, identification_create_from_string(arg)); continue; case 'l': - lifetime = atoi(arg); + lifetime = atoi(arg) * 24 * 60 * 60; if (!lifetime) { error = "invalid --lifetime value"; goto usage; } continue; + case 'D': + dateform = arg; + continue; + case 'F': + datenb = arg; + continue; + case 'T': + datena = arg; + continue; case 's': hex = arg; continue; @@ -285,6 +294,12 @@ static int issue() error = "--cakey or --keyid is required"; goto usage; } + if (!calculate_lifetime(dateform, datenb, datena, lifetime, + ¬_before, ¬_after)) + { + error = "invalid --not-before/after datetime"; + goto usage; + } if (dn && *dn) { id = identification_create_from_string(dn); @@ -363,6 +378,7 @@ static int issue() rng->destroy(rng); goto end; } + serial.ptr[0] &= 0x7F; rng->destroy(rng); } @@ -454,9 +470,6 @@ static int issue() chunk_from_chars(ASN1_SEQUENCE, 0)); } - not_before = time(NULL); - not_after = not_before + lifetime * 24 * 60 * 60; - cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_SIGNING_KEY, private, BUILD_SIGNING_CERT, ca, BUILD_PUBLIC_KEY, public, BUILD_SUBJECT, id, @@ -552,6 +565,9 @@ static void __attribute__ ((constructor))reg() {"dn", 'd', 1, "distinguished name to include as subject"}, {"san", 'a', 1, "subjectAltName to include in certificate"}, {"lifetime", 'l', 1, "days the certificate is valid, default: 1095"}, + {"not-before", 'F', 1, "date/time the validity of the cert starts"}, + {"not-after", 'T', 1, "date/time the validity of the cert ends"}, + {"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"}, {"serial", 's', 1, "serial number in hex, default: random"}, {"ca", 'b', 0, "include CA basicConstraint, default: no"}, {"pathlen", 'p', 1, "set path length constraint"}, diff --git a/src/pki/commands/print.c b/src/pki/commands/print.c index 077c1ef3e..5b00db23c 100644 --- a/src/pki/commands/print.c +++ b/src/pki/commands/print.c @@ -16,9 +16,11 @@ #include "pki.h" #include +#include #include #include #include +#include #include #include @@ -387,6 +389,84 @@ static void print_crl(crl_t *crl) enumerator->destroy(enumerator); } +/** + * Print AC specific information + */ +static void print_ac(ac_t *ac) +{ + ac_group_type_t type; + identification_t *id; + enumerator_t *groups; + chunk_t chunk; + bool first = TRUE; + + chunk = chunk_skip_zero(ac->get_serial(ac)); + printf("serial: %#B\n", &chunk); + + id = ac->get_holderIssuer(ac); + if (id) + { + printf("hissuer: \"%Y\"\n", id); + } + chunk = chunk_skip_zero(ac->get_holderSerial(ac)); + if (chunk.ptr) + { + printf("hserial: %#B\n", &chunk); + } + groups = ac->create_group_enumerator(ac); + while (groups->enumerate(groups, &type, &chunk)) + { + int oid; + char *str; + + if (first) + { + printf("groups: "); + first = FALSE; + } + else + { + printf(" "); + } + switch (type) + { + case AC_GROUP_TYPE_STRING: + printf("%.*s", (int)chunk.len, chunk.ptr); + break; + case AC_GROUP_TYPE_OID: + oid = asn1_known_oid(chunk); + if (oid == OID_UNKNOWN) + { + str = asn1_oid_to_string(chunk); + if (str) + { + printf("%s", str); + } + else + { + printf("OID:%#B", &chunk); + } + } + else + { + printf("%s", oid_names[oid].name); + } + break; + case AC_GROUP_TYPE_OCTETS: + printf("%#B", &chunk); + break; + } + printf("\n"); + } + groups->destroy(groups); + + chunk = ac->get_authKeyIdentifier(ac); + if (chunk.ptr) + { + printf("authkey: %#B\n", &chunk); + } +} + /** * Print certificate information */ @@ -432,6 +512,9 @@ static void print_cert(certificate_t *cert) case CERT_X509_CRL: print_crl((crl_t*)cert); break; + case CERT_X509_AC: + print_ac((ac_t*)cert); + break; default: printf("parsing certificate subtype %N not implemented\n", certificate_type_names, cert->get_type(cert)); @@ -472,6 +555,11 @@ static int print() type = CRED_CERTIFICATE; subtype = CERT_X509_CRL; } + else if (streq(arg, "ac")) + { + type = CRED_CERTIFICATE; + subtype = CERT_X509_AC; + } else if (streq(arg, "pub")) { type = CRED_PUBLIC_KEY; @@ -558,7 +646,7 @@ static void __attribute__ ((constructor))reg() command_register((command_t) { print, 'a', "print", "print a credential in a human readable form", - {"[--in file] [--type rsa-priv|ecdsa-priv|pub|x509|crl]"}, + {"[--in file] [--type rsa-priv|ecdsa-priv|pub|x509|crl|ac]"}, { {"help", 'h', 0, "show usage information"}, {"in", 'i', 1, "input file, default: stdin"}, diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c index c28c9c291..b684d54a7 100644 --- a/src/pki/commands/self.c +++ b/src/pki/commands/self.c @@ -60,8 +60,8 @@ static int self() int inhibit_mapping = X509_NO_CONSTRAINT, require_explicit = X509_NO_CONSTRAINT; chunk_t serial = chunk_empty; chunk_t encoding = chunk_empty; - time_t lifetime = 1095; - time_t not_before, not_after; + time_t not_before, not_after, lifetime = 1095 * 24 * 60 * 60; + char *datenb = NULL, *datena = NULL, *dateform = NULL; x509_flag_t flags = 0; x509_cert_policy_t *policy = NULL; char *arg; @@ -114,14 +114,24 @@ static int self() case 'a': san->insert_last(san, identification_create_from_string(arg)); continue; + continue; case 'l': - lifetime = atoi(arg); + lifetime = atoi(arg) * 24 * 60 * 60; if (!lifetime) { error = "invalid --lifetime value"; goto usage; } continue; + case 'D': + dateform = arg; + continue; + case 'F': + datenb = arg; + continue; + case 'T': + datena = arg; + continue; case 's': hex = arg; continue; @@ -250,6 +260,12 @@ static int self() error = "--dn is required"; goto usage; } + if (!calculate_lifetime(dateform, datenb, datena, lifetime, + ¬_before, ¬_after)) + { + error = "invalid --not-before/after datetime"; + goto usage; + } id = identification_create_from_string(dn); if (id->get_type(id) != ID_DER_ASN1_DN) { @@ -314,10 +330,9 @@ static int self() rng->destroy(rng); goto end; } + serial.ptr[0] &= 0x7F; rng->destroy(rng); } - not_before = time(NULL); - not_after = not_before + lifetime * 24 * 60 * 60; cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_SIGNING_KEY, private, BUILD_PUBLIC_KEY, public, BUILD_SUBJECT, id, BUILD_NOT_BEFORE_TIME, not_before, @@ -405,6 +420,9 @@ static void __attribute__ ((constructor))reg() {"dn", 'd', 1, "subject and issuer distinguished name"}, {"san", 'a', 1, "subjectAltName to include in certificate"}, {"lifetime", 'l', 1, "days the certificate is valid, default: 1095"}, + {"not-before", 'F', 1, "date/time the validity of the cert starts"}, + {"not-after", 'T', 1, "date/time the validity of the cert ends"}, + {"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"}, {"serial", 's', 1, "serial number in hex, default: random"}, {"ca", 'b', 0, "include CA basicConstraint, default: no"}, {"pathlen", 'p', 1, "set path length constraint"}, diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c index 4f9dd291d..c9eebbf59 100644 --- a/src/pki/commands/signcrl.c +++ b/src/pki/commands/signcrl.c @@ -124,7 +124,8 @@ static int sign_crl() int serial_len = 0; crl_reason_t reason = CRL_REASON_UNSPECIFIED; time_t thisUpdate, nextUpdate, date = time(NULL); - time_t lifetime = 15; + time_t lifetime = 15 * 24 * 60 * 60; + char *datetu = NULL, *datenu = NULL, *dateform = NULL; linked_list_t *list, *cdps; enumerator_t *enumerator, *lastenum = NULL; x509_cdp_t *cdp; @@ -161,13 +162,22 @@ static int sign_crl() lastupdate = arg; continue; case 'l': - lifetime = atoi(arg); + lifetime = atoi(arg) * 24 * 60 * 60; if (!lifetime) { - error = "invalid lifetime"; + error = "invalid --lifetime value"; goto usage; } continue; + case 'D': + dateform = arg; + continue; + case 'F': + datetu = arg; + continue; + case 'T': + datenu = arg; + continue; case 'z': serial_len = read_serial(arg, serial, sizeof(serial)); if (serial_len < 0) @@ -275,6 +285,12 @@ static int sign_crl() error = "--cakey or --keyid is required"; goto usage; } + if (!calculate_lifetime(dateform, datetu, datenu, lifetime, + &thisUpdate, &nextUpdate)) + { + error = "invalid --this/next-update datetime"; + goto usage; + } ca = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, BUILD_FROM_FILE, cacert, BUILD_END); @@ -321,9 +337,6 @@ static int sign_crl() goto error; } - thisUpdate = time(NULL); - nextUpdate = thisUpdate + lifetime * 24 * 60 * 60; - if (basecrl) { lastcrl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL, @@ -442,6 +455,9 @@ static void __attribute__ ((constructor))reg() {"cakey", 'k', 1, "CA private key file"}, {"cakeyid", 'x', 1, "keyid on smartcard of CA private key"}, {"lifetime", 'l', 1, "days the CRL gets a nextUpdate, default: 15"}, + {"this-update", 'F', 1, "date/time the validity of the CRL starts"}, + {"next-update", 'T', 1, "date/time the validity of the CRL ends"}, + {"dateform", 'D', 1, "strptime(3) input format, default: %d.%m.%y %T"}, {"lastcrl", 'a', 1, "CRL of lastUpdate to copy revocations from"}, {"basecrl", 'b', 1, "base CRL to create a delta CRL for"}, {"crluri", 'u', 1, "freshest delta CRL URI to include"}, diff --git a/src/pki/man/Makefile.am b/src/pki/man/Makefile.am index 618bd4093..4c901ae3c 100644 --- a/src/pki/man/Makefile.am +++ b/src/pki/man/Makefile.am @@ -4,6 +4,7 @@ man1_MANS = \ pki---self.1 \ pki---issue.1 \ pki---signcrl.1 \ + pki---acert.1 \ pki---req.1 \ pki---pkcs7.1 \ pki---keyid.1 \ diff --git a/src/pki/man/pki---acert.1.in b/src/pki/man/pki---acert.1.in new file mode 100644 index 000000000..ec1d8be6e --- /dev/null +++ b/src/pki/man/pki---acert.1.in @@ -0,0 +1,130 @@ +.TH "PKI \-\-ACERT" 1 "2014-02-05" "@PACKAGE_VERSION@" "strongSwan" +. +.SH "NAME" +. +pki \-\-acert \- Issue an attribute certificate +. +.SH "SYNOPSIS" +. +.SY pki\ \-\-acert +.OP \-\-in file +.OP \-\-group membership +.BI \-\-issuerkey\~ file |\-\-issuerkeyid\~ hex +.BI \-\-issuercert\~ file +.OP \-\-lifetime hours +.OP \-\-not-before datetime +.OP \-\-not-after datetime +.OP \-\-serial hex +.OP \-\-digest digest +.OP \-\-outform encoding +.OP \-\-debug level +.YS +. +.SY pki\ \-\-acert +.BI \-\-options\~ file +.YS +. +.SY "pki \-\-acert" +.B \-h +| +.B \-\-help +.YS +. +.SH "DESCRIPTION" +. +This sub-command of +.BR pki (1) +is used to issue an attribute certificate using an issuer certificate with its +private key and the holder certificate. +. +.SH "OPTIONS" +. +.TP +.B "\-h, \-\-help" +Print usage information with a summary of the available options. +.TP +.BI "\-v, \-\-debug " level +Set debug level, default: 1. +.TP +.BI "\-+, \-\-options " file +Read command line options from \fIfile\fR. +.TP +.BI "\-i, \-\-in " file +Holder certificate to issue an attribute certificate for. If not given the +certificate is read from \fISTDIN\fR. +.TP +.BI "\-m, \-\-group " membership +Group membership the attribute certificate shall certify. The specified group +is included as a string. To include multiple groups, the option can be repeated. +.TP +.BI "\-k, \-\-issuerkey " file +Issuer private key file. Either this or +.B \-\-issuerkeyid +is required. +.TP +.BI "\-x, \-\-issuerkeyid " hex +Key ID of a issuer private key on a smartcard. Either this or +.B \-\-issuerkey +is required. +.TP +.BI "\-c, \-\-issuercert " file +Issuer certificate file. Required. +.TP +.BI "\-l, \-\-lifetime " hours +Hours the attribute certificate is valid, default: 24. Ignored if both +an absolute start and end time are given. +.TP +.BI "\-F, \-\-not-before " datetime +Absolute time when the validity of the AC begins. The datetime format is +defined by the +.B \-\-dateform +option. +.TP +.BI "\-T, \-\-not-after " datetime +Absolute time when the validity of the AC ends. The datetime format is +defined by the +.B \-\-dateform +option. +.TP +.BI "\-D, \-\-dateform " form +strptime(3) format for the +.B \-\-not\-before +and +.B \-\-not\-after +options, default: +.B %d.%m.%y %T +.TP +.BI "\-s, \-\-serial " hex +Serial number in hex. It is randomly allocated by default. +.TP +.BI "\-g, \-\-digest " digest +Digest to use for signature creation. One of \fImd5\fR, \fIsha1\fR, +\fIsha224\fR, \fIsha256\fR, \fIsha384\fR, or \fIsha512\fR. Defaults to +\fIsha1\fR. +.TP +.BI "\-f, \-\-outform " encoding +Encoding of the created certificate file. Either \fIder\fR (ASN.1 DER) or +\fIpem\fR (Base64 PEM), defaults to \fIder\fR. +. +.SH "EXAMPLES" +. +To save repetitive typing, command line options can be stored in files. +Lets assume +.I acert.opt +contains the following contents: +.PP +.EX + --issuercert aacert.der --issuerkey aakey.der --digest sha256 --lifetime 4 +.EE +.PP +Then the following command can be used to issue an attribute certificate based +on a holder certificate and the options above: +.PP +.EX + pki --acert --options acert.opt --in holder.der --group sales --group finance -f pem +.EE +.PP +. +.SH "SEE ALSO" +. +.BR pki (1) diff --git a/src/pki/man/pki---issue.1.in b/src/pki/man/pki---issue.1.in index 3fad1ae8a..375cb2fe4 100644 --- a/src/pki/man/pki---issue.1.in +++ b/src/pki/man/pki---issue.1.in @@ -14,6 +14,8 @@ pki \-\-issue \- Issue a certificate using a CA certificate and key .OP \-\-dn subject-dn .OP \-\-san subjectAltName .OP \-\-lifetime days +.OP \-\-not-before datetime +.OP \-\-not-after datetime .OP \-\-serial hex .OP \-\-flag flag .OP \-\-digest digest @@ -88,7 +90,28 @@ Subject distinguished name (DN) of the issued certificate. subjectAltName extension to include in certificate. Can be used multiple times. .TP .BI "\-l, \-\-lifetime " days -Days the certificate is valid, default: 1095. +Days the certificate is valid, default: 1095. Ignored if both +an absolute start and end time are given. +.TP +.BI "\-F, \-\-not-before " datetime +Absolute time when the validity of the certificate begins. The datetime format +is defined by the +.B \-\-dateform +option. +.TP +.BI "\-T, \-\-not-after " datetime +Absolute time when the validity of the certificate ends. The datetime format is +defined by the +.B \-\-dateform +option. +.TP +.BI "\-D, \-\-dateform " form +strptime(3) format for the +.B \-\-not\-before +and +.B \-\-not\-after +options, default: +.B %d.%m.%y %T .TP .BI "\-s, \-\-serial " hex Serial number in hex. It is randomly allocated by default. @@ -176,4 +199,4 @@ given PKCS#10 certificate request and the options above: . .SH "SEE ALSO" . -.BR pki (1) \ No newline at end of file +.BR pki (1) diff --git a/src/pki/man/pki---print.1.in b/src/pki/man/pki---print.1.in index 8d3345edc..434d4ea16 100644 --- a/src/pki/man/pki---print.1.in +++ b/src/pki/man/pki---print.1.in @@ -46,8 +46,9 @@ Input file. If not given the input is read from \fISTDIN\fR. .BI "\-t, \-\-type " type Type of input. One of \fIrsa-priv\fR (RSA private key), \fIecdsa-priv\fR (ECDSA private key), \fIpub\fR (public key), \fIx509\fR (X.509 certificate), \fIcrl\fR -(Certificate Revocation List, CRL), defaults to \fIx509\fR. +(Certificate Revocation List, CRL), \fIac\fR (Attribute Certificate), +defaults to \fIx509\fR. . .SH "SEE ALSO" . -.BR pki (1) \ No newline at end of file +.BR pki (1) diff --git a/src/pki/man/pki---self.1.in b/src/pki/man/pki---self.1.in index ee42cf9a0..5e6e78bd0 100644 --- a/src/pki/man/pki---self.1.in +++ b/src/pki/man/pki---self.1.in @@ -14,6 +14,8 @@ pki \-\-self \- Create a self-signed certificate .BI \-\-dn\~ distinguished-name .OP \-\-san subjectAltName .OP \-\-lifetime days +.OP \-\-not-before datetime +.OP \-\-not-after datetime .OP \-\-serial hex .OP \-\-flag flag .OP \-\-digest digest @@ -75,7 +77,28 @@ Subject and issuer distinguished name (DN). Required. subjectAltName extension to include in certificate. Can be used multiple times. .TP .BI "\-l, \-\-lifetime " days -Days the certificate is valid, default: 1095. +Days the certificate is valid, default: 1095. Ignored if both +an absolute start and end time are given. +.TP +.BI "\-F, \-\-not-before " datetime +Absolute time when the validity of the certificate begins. The datetime format +is defined by the +.B \-\-dateform +option. +.TP +.BI "\-T, \-\-not-after " datetime +Absolute time when the validity of the certificate ends. The datetime format is +defined by the +.B \-\-dateform +option. +.TP +.BI "\-D, \-\-dateform " form +strptime(3) format for the +.B \-\-not\-before +and +.B \-\-not\-after +options, default: +.B %d.%m.%y %T .TP .BI "\-s, \-\-serial " hex Serial number in hex. It is randomly allocated by default. @@ -145,4 +168,4 @@ Generate a self-signed certificate using the given RSA key: . .SH "SEE ALSO" . -.BR pki (1) \ No newline at end of file +.BR pki (1) diff --git a/src/pki/man/pki---signcrl.1.in b/src/pki/man/pki---signcrl.1.in index 6ba96f6bc..bd6cba547 100644 --- a/src/pki/man/pki---signcrl.1.in +++ b/src/pki/man/pki---signcrl.1.in @@ -10,6 +10,8 @@ pki \-\-signcrl \- Issue a Certificate Revocation List (CRL) using a CA certific .BI \-\-cakey\~ file |\-\-cakeyid\~ hex .BI \-\-cacert\~ file .OP \-\-lifetime days +.OP \-\-this-update datetime +.OP \-\-next-update datetime .OP \-\-lastcrl crl .OP \-\-basecrl crl .OP \-\-crluri uri @@ -62,7 +64,28 @@ is required. CA certificate file. Required. .TP .BI "\-l, \-\-lifetime " days -Days until the CRL gets a nextUpdate, default: 15. +Days until the CRL gets a nextUpdate, default: 15. Ignored if both +an absolute start and end time are given. +.TP +.BI "\-F, \-\-this-update " datetime +Absolute time when the validity of the CRL begins. The datetime format is +defined by the +.B \-\-dateform +option. +.TP +.BI "\-T, \-\-next-update " datetime +Absolute time when the validity of the CRL end. The datetime format is +defined by the +.B \-\-dateform +option. +.TP +.BI "\-D, \-\-dateform " form +strptime(3) format for the +.B \-\-this\-update +and +.B \-\-next\-update +options, default: +.B %d.%m.%y %T .TP .BI "\-a, \-\-lastcrl " crl CRL of lastUpdate to copy revocations from. @@ -121,4 +144,4 @@ number, but no reason: .PP .SH "SEE ALSO" . -.BR pki (1) \ No newline at end of file +.BR pki (1) diff --git a/src/pki/man/pki.1.in b/src/pki/man/pki.1.in index 8dfc53af3..f347031b4 100644 --- a/src/pki/man/pki.1.in +++ b/src/pki/man/pki.1.in @@ -49,6 +49,9 @@ Issue a certificate using a CA certificate and key. .B "\-c, \-\-signcrl" Issue a CRL using a CA certificate and key. .TP +.B "\-z, \-\-acert" +Issue an attribute certificate. +.TP .B "\-r, \-\-req" Create a PKCS#10 certificate request. .TP @@ -148,6 +151,7 @@ certificates with the \-\-crl option. .BR pki\ \-\-self (1), .BR pki\ \-\-issue (1), .BR pki\ \-\-signcrl (1), +.BR pki\ \-\-acert (1), .BR pki\ \-\-req (1), .BR pki\ \-\-pkcs7 (1), .BR pki\ \-\-keyid (1), diff --git a/src/pki/pki.c b/src/pki/pki.c index eb614dd7f..ae4ef1cb0 100644 --- a/src/pki/pki.c +++ b/src/pki/pki.c @@ -13,9 +13,11 @@ * for more details. */ +#define _GNU_SOURCE #include "command.h" #include "pki.h" +#include #include #include @@ -101,6 +103,56 @@ bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type) return FALSE; } +/** + * See header + */ +bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span, + time_t *nb, time_t *na) +{ + struct tm tm; + time_t now; + char *end; + + if (!format) + { + format = "%d.%m.%y %T"; + } + + now = time(NULL); + + localtime_r(&now, &tm); + if (nbstr) + { + end = strptime(nbstr, format, &tm); + if (end == NULL || *end != '\0') + { + return FALSE; + } + } + *nb = mktime(&tm); + + localtime_r(&now, &tm); + if (nastr) + { + end = strptime(nastr, format, &tm); + if (end == NULL || *end != '\0') + { + return FALSE; + } + } + *na = mktime(&tm); + + if (!nbstr && nastr) + { + *nb = *na - span; + } + else if (!nastr) + { + *na = *nb + span; + } + return TRUE; +} + /** * Callback credential set pki uses */ @@ -188,4 +240,3 @@ int main(int argc, char *argv[]) atexit(remove_callback); return command_dispatch(argc, argv); } - diff --git a/src/pki/pki.h b/src/pki/pki.h index 09c50c6c2..616fac44a 100644 --- a/src/pki/pki.h +++ b/src/pki/pki.h @@ -33,4 +33,21 @@ */ bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type); +/** + * Calculate start/end lifetime for certificates. + * + * If both nbstr and nastr are given, span is ignored. Otherwise missing + * arguments are calculated, or assumed to be now. + * + * @param format strptime() format, NULL for default: %d.%m.%y %T + * @param nbstr string describing notBefore datetime, or NULL + * @param nastr string describing notAfter datetime, or NULL + * @param span lifetime span, from notBefore to notAfter + * @param nb calculated notBefore time + * @param na calculated notAfter time + * @return TRUE of nb/na calculated successfully + */ +bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span, + time_t *nb, time_t *na); + #endif /** PKI_H_ @}*/ diff --git a/testing/scripts/recipes/013_strongswan.mk b/testing/scripts/recipes/013_strongswan.mk index 438e6668a..c4142086f 100644 --- a/testing/scripts/recipes/013_strongswan.mk +++ b/testing/scripts/recipes/013_strongswan.mk @@ -76,6 +76,7 @@ CONFIG_OPTS = \ --enable-unbound \ --enable-ipseckey \ --enable-dnscert \ + --enable-acert \ --enable-cmd \ --enable-libipsec \ --enable-kernel-libipsec \ diff --git a/testing/tests/ikev2/acert-cached/description.txt b/testing/tests/ikev2/acert-cached/description.txt new file mode 100644 index 000000000..42f7432bc --- /dev/null +++ b/testing/tests/ikev2/acert-cached/description.txt @@ -0,0 +1,11 @@ +

The roadwarriors carol and dave set up a connection each +to gateway moon. The authentication is based on X.509 certificates. +To authorize clients, moon uses locally cached attribute certificates. +While for carol a valid attribute certificate for the group sales +is available, dave's attribute certificates are either expired or +do not grant permissions for the sales group.

+

Upon the successful establishment of the IPsec tunnels, leftfirewall=yes +automatically inserts iptables-based firewall rules that let pass the tunneled traffic. +In order to test both tunnel and firewall, both carol and dave try +to ping the client alice behind the gateway moon, but dave fails +to do so.

diff --git a/testing/tests/ikev2/acert-cached/evaltest.dat b/testing/tests/ikev2/acert-cached/evaltest.dat new file mode 100644 index 000000000..682c55ce2 --- /dev/null +++ b/testing/tests/ikev2/acert-cached/evaltest.dat @@ -0,0 +1,12 @@ +carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol@strongswan.org.*moon.strongswan.org::YES +dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave@strongswan.org.*moon.strongswan.org::NO +moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol@strongswan.org::YES +moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave@strongswan.org::NO +moon::cat /var/log/daemon.log::constraint check failed: group membership to 'sales' required::YES +dave::cat /var/log/daemon.log::received AUTHENTICATION_FAILED notify error::YES +carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES +dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO +moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES +moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES +moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::NO +moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::NO diff --git a/testing/tests/ikev2/acert-cached/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/acert-cached/hosts/carol/etc/ipsec.conf new file mode 100644 index 000000000..e72f78742 --- /dev/null +++ b/testing/tests/ikev2/acert-cached/hosts/carol/etc/ipsec.conf @@ -0,0 +1,20 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + +conn home + left=PH_IP_CAROL + leftcert=carolCert.pem + leftid=carol@strongswan.org + leftfirewall=yes + right=PH_IP_MOON + rightid=@moon.strongswan.org + rightsubnet=10.1.0.0/16 + keyexchange=ikev2 + auto=add diff --git a/testing/tests/ikev2/acert-cached/hosts/carol/etc/strongswan.conf b/testing/tests/ikev2/acert-cached/hosts/carol/etc/strongswan.conf new file mode 100644 index 000000000..dc937641c --- /dev/null +++ b/testing/tests/ikev2/acert-cached/hosts/carol/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown +} diff --git a/testing/tests/ikev2/acert-cached/hosts/dave/etc/ipsec.conf b/testing/tests/ikev2/acert-cached/hosts/dave/etc/ipsec.conf new file mode 100644 index 000000000..65c9819bb --- /dev/null +++ b/testing/tests/ikev2/acert-cached/hosts/dave/etc/ipsec.conf @@ -0,0 +1,20 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + +conn home + left=PH_IP_DAVE + leftcert=daveCert.pem + leftid=dave@strongswan.org + leftfirewall=yes + right=PH_IP_MOON + rightid=@moon.strongswan.org + rightsubnet=10.1.0.0/16 + keyexchange=ikev2 + auto=add diff --git a/testing/tests/ikev2/acert-cached/hosts/dave/etc/strongswan.conf b/testing/tests/ikev2/acert-cached/hosts/dave/etc/strongswan.conf new file mode 100644 index 000000000..dc937641c --- /dev/null +++ b/testing/tests/ikev2/acert-cached/hosts/dave/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown +} diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.conf new file mode 100644 index 000000000..fbffbad62 --- /dev/null +++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.conf @@ -0,0 +1,20 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + +conn rw + left=PH_IP_MOON + leftcert=moonCert.pem + leftid=@moon.strongswan.org + leftsubnet=10.1.0.0/16 + leftfirewall=yes + right=%any + rightgroups=sales + keyexchange=ikev2 + auto=add diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/aacerts/aa.pem b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/aacerts/aa.pem new file mode 100644 index 000000000..fbfa7ee8b --- /dev/null +++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/aacerts/aa.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKjCCAhKgAwIBAgIIFU5+Fa8cF2EwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE +BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u +Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDcwODUwMzVaFw0yMjA0MjYwODUwMzVaMEAx +CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRYwFAYDVQQD +Ew1zdHJvbmdTd2FuIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +y6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTFFbSbpQJxWk603BJH +hlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsAQ3yWfkZZK1jxTdTP +dvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqYzdWFCUINTXUGEr/L +lt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNTjS2xaaklUCq2auR/ +QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf+7suyGczSRMP6+5N +jqNqab7l/SHwHQMVEE5ihwIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2 +bbO15eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAakPgMKVjkQmpI1VROcetvZzM +ZHMWwdu9IcwNpi/8qs2qNh6wCYv9c4V6O4zRCB1u8TuAIQiwLNZgjk+OKKLzvUik +gBRogn/apXsvAtfu9ODv5GuS6F38OYWDu/c3fiCZB2MKTtmEro2EkxxMw4DkfJ02 +R/xrhAnjeQlRQOChgQ3fHNmH9gVNaKXNq+JaoU2TfHFwuYMMe6q1L+vhOaBd58YA +6wPHOOLcIEaebHIqa4duAE5txJsZCEEySrr5stqo4j7929BAw+U6f+6Wb+UAEW6g +91PKAl5QVbAzgPFWoPkOTNdDOprT+B4eGx0EC2QTEtxxDv5589choF7BMRCzsQ== +-----END CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/carol-sales-finance.pem b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/carol-sales-finance.pem new file mode 100644 index 000000000..406c15700 --- /dev/null +++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/carol-sales-finance.pem @@ -0,0 +1,18 @@ +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIIC+DCCAeACAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp +bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe +pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP +BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG +MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW +MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIIWCKrRUelL+kw +IhgPMjAxNDAyMDcwODU4MTJaGA8yMDIyMDQyNjA4NTgxMlowIjAgBggrBgEFBQcK +BDEUMBIwEAwFc2FsZXMMB2ZpbmFuY2UwfzByBgNVHSMEazBpCwHqxzoCXPi2xMHh +2q7CV/ZSsLChSaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJv +bmdTd2FuMRswGQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCCBVOfhWvHBdhMAkG +A1UdOAQCBQAwDQYJKoZIhvcNAQEFBQADggEBADNSv52dbBOp30L0kJse9HqWMBaR +SA5IDrF1FMLVZfI0Vb9XgEmk1SXAnMmPm7bfk+2w0Rd1jL7D905nel3LXuvohSR9 +wd4Vo8XX3WUlzNfjUEFFJb0nU2ybr7SmxF+K4wGnhvBAym2y/hNA0glp2hNjYTds +g+RUpM4bSqP5DpUfRBl19VHeEu/OymoACOzuHuNc1IndYM1mkSJYumX6YW60DpF/ +TaK1So3FyEWucHeoFCziNbclrjWwB8OS3JfCOl95rxu+0JhyWc+3x1E50W8DaAnY +ZRyYxDjYT9/E9xyzV45yo0xFODIgDgfKMsDjfUmfny3dTesdFUf3Ar3vTfA= +-----END ATTRIBUTE CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-marketing.pem b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-marketing.pem new file mode 100644 index 000000000..2f646c39d --- /dev/null +++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-marketing.pem @@ -0,0 +1,18 @@ +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIIC9DCCAdwCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp +bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf +pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR +BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg +RjBEpEIwQDELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x +FjAUBgNVBAMTDXN0cm9uZ1N3YW4gQUEwDQYJKoZIhvcNAQEFBQACCCPxWgWKmOUM +MCIYDzIwMTQwMjA3MDg1OTM3WhgPMjAyMjA0MjYwODU5MzdaMB0wGwYIKwYBBQUH +CgQxDzANMAsMCW1hcmtldGluZzB/MHIGA1UdIwRrMGkLAerHOgJc+LbEweHarsJX +9lKwsKFJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3 +YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIIFU5+Fa8cF2EwCQYDVR04 +BAIFADANBgkqhkiG9w0BAQUFAAOCAQEAThlKhGVv34sfnCSQn6nYUdxMhboTuC98 ++DgvTQ/tH0hddCJNg00SpO8AbStwEsqHFaSqFzAGHcMk+XUrBRSGszAwg8nKAKfT +MCvJbK6lWQcPF0WPSSk9/r1TLan4I9xhneNIIGQf1fnNo7NrQnmhJjolUgXQNwFA +qZgKBsk0jWcOSvI0bpK90km5flCHn/OA1rDCdaPuMwreDhvNDoApORYFPZVsLhid +CXSqT+FWfm2NfegS+Q4VHP3YLbY4vLepCerU9aMTUIPit0kf1N8piG/l6AUno1XP +VrcTvruQUWQb08H9aYt7l7kyhzOKkuXjVbdn5egZnK0m4WKmV50guA== +-----END ATTRIBUTE CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-sales-expired.pem b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-sales-expired.pem new file mode 100644 index 000000000..d42038469 --- /dev/null +++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/acerts/dave-sales-expired.pem @@ -0,0 +1,18 @@ +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIIC8DCCAdgCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp +bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf +pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR +BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg +RjBEpEIwQDELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x +FjAUBgNVBAMTDXN0cm9uZ1N3YW4gQUEwDQYJKoZIhvcNAQEFBQACCEuGbFvrRrtr +MCIYDzIwMTQwMjA3MDgwMTE3WhgPMjAxNDAyMDcwOTAxMTdaMBkwFwYIKwYBBQUH +CgQxCzAJMAcMBXNhbGVzMH8wcgYDVR0jBGswaQsB6sc6Alz4tsTB4dquwlf2UrCw +oUmkRzBFMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEb +MBkGA1UEAxMSc3Ryb25nU3dhbiBSb290IENBgggVTn4VrxwXYTAJBgNVHTgEAgUA +MA0GCSqGSIb3DQEBBQUAA4IBAQBYnOq716FJ079kXAt8vmi2GpEyyCqSBqqjr0lR +X9mGQqWKmpj88ZP61tCooCy8HaJsgKBvedKJHJ4e/YxR+fqBDkT4apFu4wX8P/xh +yKy6/RMAdTtkwVTE6flXdQryCQ/PGhSMuwwH/URFg65mixAatyyaoat4+mZ506u3 +F9ZZXkHPP4nZXAJqYjLLcNXPqC4lGoXXT+9dgsm6RLAdnBXT1GGff9tmqt9CcspW +XPjoqy9AxNr6FnItvMGw0CC6MPyVOJImlSxdhFW7waZkpNfmGzRdylXMwHXk8PbW +gjmlDUbyWquu8xBlpron3X/Jx3YNGVNrhgfZLlmhzCRouMqc +-----END ATTRIBUTE CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/private/aa.pem b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/private/aa.pem new file mode 100644 index 000000000..a4e001791 --- /dev/null +++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/ipsec.d/private/aa.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAy6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTF +FbSbpQJxWk603BJHhlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsA +Q3yWfkZZK1jxTdTPdvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqY +zdWFCUINTXUGEr/Llt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNT +jS2xaaklUCq2auR/QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf ++7suyGczSRMP6+5NjqNqab7l/SHwHQMVEE5ihwIDAQABAoIBAQCIvn5QfkYUG87+ +eyirV2xTjdMw/Md1UfBgP4yTTsmpqr79K5fUqg5zLX+0VfJDbRaPEICBKCVrKDfz +d5QFwAsTiXf8CKwQqFdEunWmJfgppEQIYGzN40IciNloLHDghEnEI9GGpv9glLQn +DugjRprEUmWJ+HpB0LH9fc2Ums704Fcd8ud3bStCRxU1TA5VGBHmnyK5/n1Lb1oB +01LoW8ins8lATuV+MAaWZgmCbPajfXY9wQGq3IDMVlOUOTxRo742T1GTrwBZR8ot +mgs/Gs1XkJRC1x9Z9Z1Cej1iC5llv0zX8AUdejczGHQGHj1a1Dg8FpRneW6rrLyK +vvKR8jtRAoGBAOpyk63yCPM2LqU4US5aHXPoLyyGeo4v7okTKIuoUfosQ4XJvylM +lEYoFVFKYBKcXRQhmeWyILtto2BBDnG1HWAi1MbUWLxDNEYieurzJiv4i0XbR6cH +mLhMMlQyKmwLRF5v3EiupjKBZRk2iYcx4eeL3gsUWUzRPeWJHKDgYF4PAoGBAN5i +xyOsU/32gQ6vLQxt8us6n3OBr1PiFg8JIdADPnKOCxJ5uS8dkqOQHCMKyvS9MWrf +3Wj4MOBEgW7fBBAxkvjJdPhBW70/pGM46mb991dTHJ4gIAzGxgvJIqw/FjqEC7Oo +vWDRS4dxW56Rs2tdLn2GRvvlS3+3z90twqS/t6wJAoGBAJpzhzT2Gc1YaZxxIJI/ +zd15HfLgWUbo7uWhGHoBFpiQpp8yDNzBVYFukLSwIeDA4FUN2dxH4GZ50ULtOP3S +Cps19yVR6W+Fep+lwYKdUw1uvRn1Xxv71jG8CQAM2IO7XHw2h1HetSDau+bDVhEZ +3LB1JX/5FOeVhYh9Lr4Rc4sjAoGBAJCTCv+oEtqyHOjc/Z5tBFXkwLCpCMCx5MFV +oIPI+BolOhGCzN9SjHiFQaWOaK9/J9dhPmH1qGDEaJkZp1yXvgK7ha23X9rCuy4+ +XDUkul4tDBfIrs1flHUpB7+PK/ZSzgC4nJWKu12MVpHaCxirdYPpfdBZGyIm753N +GBNfCBtxAoGAKkrHlsfq7GVVU7Jj1AlNCwmlm21vSJ45G3cNR1GpgdplB5JR1ldV +2kxA4xm8uFVIJ60OQ9VZ5Svaovqh8iX2sndSOZMefjH3qiDu/4mJqRA3xV5ugon3 +RAzinJzUU4tnk9pajOMD3FHOHvUO4hAJjVYEzqLIIRE7QhPuEpLevZ4= +-----END RSA PRIVATE KEY----- diff --git a/testing/tests/ikev2/acert-cached/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/acert-cached/hosts/moon/etc/strongswan.conf new file mode 100644 index 000000000..cd836a2b7 --- /dev/null +++ b/testing/tests/ikev2/acert-cached/hosts/moon/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation acert hmac xcbc stroke kernel-netlink socket-default updown +} diff --git a/testing/tests/ikev2/acert-cached/posttest.dat b/testing/tests/ikev2/acert-cached/posttest.dat new file mode 100644 index 000000000..e5b8d291c --- /dev/null +++ b/testing/tests/ikev2/acert-cached/posttest.dat @@ -0,0 +1,11 @@ +moon::ipsec stop +carol::ipsec stop +dave::ipsec stop +moon::iptables-restore < /etc/iptables.flush +carol::iptables-restore < /etc/iptables.flush +dave::iptables-restore < /etc/iptables.flush +moon::rm /etc/ipsec.d/acerts/carol-sales-finance.pem +moon::rm /etc/ipsec.d/acerts/dave-sales-expired.pem +moon::rm /etc/ipsec.d/acerts/dave-marketing.pem +moon::rm /etc/ipsec.d/private/aa.pem +moon::rm /etc/ipsec.d/aacerts/aa.pem diff --git a/testing/tests/ikev2/acert-cached/pretest.dat b/testing/tests/ikev2/acert-cached/pretest.dat new file mode 100644 index 000000000..8bbea1412 --- /dev/null +++ b/testing/tests/ikev2/acert-cached/pretest.dat @@ -0,0 +1,9 @@ +moon::iptables-restore < /etc/iptables.rules +carol::iptables-restore < /etc/iptables.rules +dave::iptables-restore < /etc/iptables.rules +moon::ipsec start +carol::ipsec start +dave::ipsec start +carol::sleep 1 +carol::ipsec up home +dave::ipsec up home diff --git a/testing/tests/ikev2/acert-cached/test.conf b/testing/tests/ikev2/acert-cached/test.conf new file mode 100644 index 000000000..f29298850 --- /dev/null +++ b/testing/tests/ikev2/acert-cached/test.conf @@ -0,0 +1,21 @@ +#!/bin/bash +# +# This configuration file provides information on the +# guest instances used for this test + +# All guest instances that are required for this test +# +VIRTHOSTS="alice moon carol winnetou dave" + +# Corresponding block diagram +# +DIAGRAM="a-m-c-w-d.png" + +# Guest instances on which tcpdump is to be started +# +TCPDUMPHOSTS="moon" + +# Guest instances on which IPsec is started +# Used for IPsec logging purposes +# +IPSECHOSTS="moon carol dave" diff --git a/testing/tests/ikev2/acert-fallback/description.txt b/testing/tests/ikev2/acert-fallback/description.txt new file mode 100644 index 000000000..0008b105a --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/description.txt @@ -0,0 +1,12 @@ +

The roadwarrior carol sets up a connection to gateway moon. +The authentication is based on X.509 certificates. To authorize clients, +moon expects attribute certificates sent inline in IKEv2 CERT payloads. +Carol has attribute certificates for both the sales and +the finance groups. The attribute certificate for finance is not +valid anymore, hence carol gets access to the sales connection +only.

+

Upon the successful establishment of the IPsec tunnel, leftfirewall=yes +automatically inserts iptables-based firewall rules that let pass the tunneled traffic. +In order to test both tunnel and firewall, carol tries to ping both +alice and venus, but only the ping for the sales related +host venus succeeds.

diff --git a/testing/tests/ikev2/acert-fallback/evaltest.dat b/testing/tests/ikev2/acert-fallback/evaltest.dat new file mode 100644 index 000000000..985f3208e --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/evaltest.dat @@ -0,0 +1,8 @@ +carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol@strongswan.org.*moon.strongswan.org::YES +moon:: ipsec status 2> /dev/null::finance.*: ESTABLISHED.*moon.strongswan.org.*dave@strongswan.org::NO +moon:: ipsec status 2> /dev/null::sales.*: ESTABLISHED.*moon.strongswan.org.*carol@strongswan.org::YES +moon::cat /var/log/daemon.log::constraint check failed: group membership to 'finance' required::YES +carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO +carol::ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES +moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES +moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES diff --git a/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.conf new file mode 100644 index 000000000..e72f78742 --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.conf @@ -0,0 +1,20 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + +conn home + left=PH_IP_CAROL + leftcert=carolCert.pem + leftid=carol@strongswan.org + leftfirewall=yes + right=PH_IP_MOON + rightid=@moon.strongswan.org + rightsubnet=10.1.0.0/16 + keyexchange=ikev2 + auto=add diff --git a/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-finance-expired.pem b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-finance-expired.pem new file mode 100644 index 000000000..3be000a3d --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-finance-expired.pem @@ -0,0 +1,18 @@ +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIIC8TCCAdkCAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp +bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe +pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP +BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG +MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW +MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIISLuuiWM2O9Yw +IhgPMjAxNDAyMDcwODQyMDVaGA8yMDE0MDIwNzA5NDIwNVowGzAZBggrBgEFBQcK +BDENMAswCQwHZmluYW5jZTB/MHIGA1UdIwRrMGkLAerHOgJc+LbEweHarsJX9lKw +sKFJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x +GzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIIFU5+Fa8cF2EwCQYDVR04BAIF +ADANBgkqhkiG9w0BAQUFAAOCAQEAaDwqM5BY9pXhlSlT3cpCJYsNCfk6T1nG5s5J +Dtgwojw0BVSoxKqcbpWdP09HOpBcwbPVk++I19wd5VsdHxtQ4/o2Hoevg4QWxUUx +t3qsdMDjg7U2iH+JppYsEDmXmx9k1hvV1OiEzHJKTDlZqXkhiItLatKSptTG3c0A +DdJVS05sdepzhkRGimE/QwO7nJ3v5ixFNIetgfbojbjhJPpNfXPIgMMHerK/hAlo +ekSwcmh9ufFuEXg8C0NunQqf6Z6FbxiUXUF9j7dvlEp3n5YFsv3WSMUjE3Sb7r8T +3e2A/LXb05ky0/SNebgS4fU9oi8acEgwN2Vqwu82hClwYAcHJg== +-----END ATTRIBUTE CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem new file mode 100644 index 000000000..a188a1d3d --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem @@ -0,0 +1,18 @@ +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIIC7zCCAdcCAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp +bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe +pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP +BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG +MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW +MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIIYO/yp98Yxu4w +IhgPMjAxNDAyMDcxMDAxNTdaGA8yMDIyMDQyNjEwMDE1N1owGTAXBggrBgEFBQcK +BDELMAkwBwwFc2FsZXMwfzByBgNVHSMEazBpCwHqxzoCXPi2xMHh2q7CV/ZSsLCh +SaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRsw +GQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCCBVOfhWvHBdhMAkGA1UdOAQCBQAw +DQYJKoZIhvcNAQEFBQADggEBAJA/duSysWae5X9JTC0BLY6gK8ggj5V9H3d60rM4 +7A8HVQldWe5QwYIRZmLS0XhMVHWiIvXJHwue2Xgs8DyAqILSCKIKpCJRhqPIxHCh +bek1nzw2YzVaU+E37He5V9PSkkRFO9tRvELhW3t4Wya7p4l6MVFW9ETOOtUqZYmt +bxAq/XEFZl/aFb2FW2RoKjUZpwxbrccCaV1hKIxtNen2ro31dNd9YHXe+fE4Fc7r +FTwbhOg3QLvZDXmiZt3LCXdMKAhayLbuSVsycuEtac44OVSvKhJ8GYykTRRn67nU +qCFNDe266KTNDqUMilrHm3FYGkpFtREOBajH4EqdMAJSdXg= +-----END ATTRIBUTE CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-fallback/hosts/carol/etc/strongswan.conf b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/strongswan.conf new file mode 100644 index 000000000..dc937641c --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/hosts/carol/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown +} diff --git a/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.conf new file mode 100644 index 000000000..37e779fef --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.conf @@ -0,0 +1,32 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + +conn finance + left=PH_IP_MOON + leftcert=moonCert.pem + leftid=@moon.strongswan.org + leftsubnet=10.1.0.10/32 + leftfirewall=yes + right=%any + rightid=*@strongswan.org + rightgroups=finance + keyexchange=ikev2 + auto=add + +conn sales + left=PH_IP_MOON + leftcert=moonCert.pem + leftid=@moon.strongswan.org + leftsubnet=10.1.0.20/32 + leftfirewall=yes + right=%any + rightgroups=sales + keyexchange=ikev2 + auto=add diff --git a/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/aacerts/aa.pem b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/aacerts/aa.pem new file mode 100644 index 000000000..fbfa7ee8b --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/aacerts/aa.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKjCCAhKgAwIBAgIIFU5+Fa8cF2EwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE +BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u +Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDcwODUwMzVaFw0yMjA0MjYwODUwMzVaMEAx +CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRYwFAYDVQQD +Ew1zdHJvbmdTd2FuIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +y6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTFFbSbpQJxWk603BJH +hlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsAQ3yWfkZZK1jxTdTP +dvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqYzdWFCUINTXUGEr/L +lt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNTjS2xaaklUCq2auR/ +QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf+7suyGczSRMP6+5N +jqNqab7l/SHwHQMVEE5ihwIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2 +bbO15eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAakPgMKVjkQmpI1VROcetvZzM +ZHMWwdu9IcwNpi/8qs2qNh6wCYv9c4V6O4zRCB1u8TuAIQiwLNZgjk+OKKLzvUik +gBRogn/apXsvAtfu9ODv5GuS6F38OYWDu/c3fiCZB2MKTtmEro2EkxxMw4DkfJ02 +R/xrhAnjeQlRQOChgQ3fHNmH9gVNaKXNq+JaoU2TfHFwuYMMe6q1L+vhOaBd58YA +6wPHOOLcIEaebHIqa4duAE5txJsZCEEySrr5stqo4j7929BAw+U6f+6Wb+UAEW6g +91PKAl5QVbAzgPFWoPkOTNdDOprT+B4eGx0EC2QTEtxxDv5589choF7BMRCzsQ== +-----END CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/private/aa.pem b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/private/aa.pem new file mode 100644 index 000000000..a4e001791 --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/ipsec.d/private/aa.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAy6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTF +FbSbpQJxWk603BJHhlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsA +Q3yWfkZZK1jxTdTPdvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqY +zdWFCUINTXUGEr/Llt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNT +jS2xaaklUCq2auR/QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf ++7suyGczSRMP6+5NjqNqab7l/SHwHQMVEE5ihwIDAQABAoIBAQCIvn5QfkYUG87+ +eyirV2xTjdMw/Md1UfBgP4yTTsmpqr79K5fUqg5zLX+0VfJDbRaPEICBKCVrKDfz +d5QFwAsTiXf8CKwQqFdEunWmJfgppEQIYGzN40IciNloLHDghEnEI9GGpv9glLQn +DugjRprEUmWJ+HpB0LH9fc2Ums704Fcd8ud3bStCRxU1TA5VGBHmnyK5/n1Lb1oB +01LoW8ins8lATuV+MAaWZgmCbPajfXY9wQGq3IDMVlOUOTxRo742T1GTrwBZR8ot +mgs/Gs1XkJRC1x9Z9Z1Cej1iC5llv0zX8AUdejczGHQGHj1a1Dg8FpRneW6rrLyK +vvKR8jtRAoGBAOpyk63yCPM2LqU4US5aHXPoLyyGeo4v7okTKIuoUfosQ4XJvylM +lEYoFVFKYBKcXRQhmeWyILtto2BBDnG1HWAi1MbUWLxDNEYieurzJiv4i0XbR6cH +mLhMMlQyKmwLRF5v3EiupjKBZRk2iYcx4eeL3gsUWUzRPeWJHKDgYF4PAoGBAN5i +xyOsU/32gQ6vLQxt8us6n3OBr1PiFg8JIdADPnKOCxJ5uS8dkqOQHCMKyvS9MWrf +3Wj4MOBEgW7fBBAxkvjJdPhBW70/pGM46mb991dTHJ4gIAzGxgvJIqw/FjqEC7Oo +vWDRS4dxW56Rs2tdLn2GRvvlS3+3z90twqS/t6wJAoGBAJpzhzT2Gc1YaZxxIJI/ +zd15HfLgWUbo7uWhGHoBFpiQpp8yDNzBVYFukLSwIeDA4FUN2dxH4GZ50ULtOP3S +Cps19yVR6W+Fep+lwYKdUw1uvRn1Xxv71jG8CQAM2IO7XHw2h1HetSDau+bDVhEZ +3LB1JX/5FOeVhYh9Lr4Rc4sjAoGBAJCTCv+oEtqyHOjc/Z5tBFXkwLCpCMCx5MFV +oIPI+BolOhGCzN9SjHiFQaWOaK9/J9dhPmH1qGDEaJkZp1yXvgK7ha23X9rCuy4+ +XDUkul4tDBfIrs1flHUpB7+PK/ZSzgC4nJWKu12MVpHaCxirdYPpfdBZGyIm753N +GBNfCBtxAoGAKkrHlsfq7GVVU7Jj1AlNCwmlm21vSJ45G3cNR1GpgdplB5JR1ldV +2kxA4xm8uFVIJ60OQ9VZ5Svaovqh8iX2sndSOZMefjH3qiDu/4mJqRA3xV5ugon3 +RAzinJzUU4tnk9pajOMD3FHOHvUO4hAJjVYEzqLIIRE7QhPuEpLevZ4= +-----END RSA PRIVATE KEY----- diff --git a/testing/tests/ikev2/acert-fallback/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/strongswan.conf new file mode 100644 index 000000000..cd836a2b7 --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/hosts/moon/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation acert hmac xcbc stroke kernel-netlink socket-default updown +} diff --git a/testing/tests/ikev2/acert-fallback/posttest.dat b/testing/tests/ikev2/acert-fallback/posttest.dat new file mode 100644 index 000000000..2ccb86a41 --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/posttest.dat @@ -0,0 +1,8 @@ +moon::ipsec stop +carol::ipsec stop +moon::iptables-restore < /etc/iptables.flush +carol::iptables-restore < /etc/iptables.flush +carol::rm /etc/ipsec.d/acerts/carol-sales.pem +carol::rm /etc/ipsec.d/acerts/carol-finance-expired.pem +moon::rm /etc/ipsec.d/private/aa.pem +moon::rm /etc/ipsec.d/aacerts/aa.pem diff --git a/testing/tests/ikev2/acert-fallback/pretest.dat b/testing/tests/ikev2/acert-fallback/pretest.dat new file mode 100644 index 000000000..baacc1605 --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/pretest.dat @@ -0,0 +1,6 @@ +moon::iptables-restore < /etc/iptables.rules +carol::iptables-restore < /etc/iptables.rules +moon::ipsec start +carol::ipsec start +carol::sleep 1 +carol::ipsec up home diff --git a/testing/tests/ikev2/acert-fallback/test.conf b/testing/tests/ikev2/acert-fallback/test.conf new file mode 100644 index 000000000..a6c21de09 --- /dev/null +++ b/testing/tests/ikev2/acert-fallback/test.conf @@ -0,0 +1,21 @@ +#!/bin/bash +# +# This configuration file provides information on the +# guest instances used for this test + +# All guest instances that are required for this test +# +VIRTHOSTS="alice venus moon carol winnetou" + +# Corresponding block diagram +# +DIAGRAM="a-v-m-c-w-d.png" + +# Guest instances on which tcpdump is to be started +# +TCPDUMPHOSTS="" + +# Guest instances on which IPsec is started +# Used for IPsec logging purposes +# +IPSECHOSTS="moon carol" diff --git a/testing/tests/ikev2/acert-inline/description.txt b/testing/tests/ikev2/acert-inline/description.txt new file mode 100644 index 000000000..948b84725 --- /dev/null +++ b/testing/tests/ikev2/acert-inline/description.txt @@ -0,0 +1,12 @@ +

The roadwarriors carol and dave set up a connection each +to gateway moon. The authentication is based on X.509 certificates. +To authorize clients, moon expects attribute certificates sent inline in +IKEv2 CERT payloads. Carol provides a valid attribute certificate for +the group sales, but dave offers two invalid attribute +certificates: One is not for the sales group, and the other is issued by +an AA that has been expired.

+

Upon the successful establishment of the IPsec tunnels, leftfirewall=yes +automatically inserts iptables-based firewall rules that let pass the tunneled traffic. +In order to test both tunnel and firewall, both carol and dave try +to ping the client alice behind the gateway moon, but dave fails +to do so.

diff --git a/testing/tests/ikev2/acert-inline/evaltest.dat b/testing/tests/ikev2/acert-inline/evaltest.dat new file mode 100644 index 000000000..ba448f81b --- /dev/null +++ b/testing/tests/ikev2/acert-inline/evaltest.dat @@ -0,0 +1,15 @@ +carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol@strongswan.org.*moon.strongswan.org::YES +dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave@strongswan.org.*moon.strongswan.org::NO +moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol@strongswan.org::YES +moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave@strongswan.org::NO +moon::cat /var/log/daemon.log::constraint check failed: group membership to 'sales' required::YES +carol::cat /var/log/daemon.log::sending attribute certificate issued by \"C=CH, O=Linux strongSwan, CN=strongSwan AA\"::YES +dave::cat /var/log/daemon.log::sending attribute certificate issued by \"C=CH, O=Linux strongSwan, CN=strongSwan AA\"::YES +dave::cat /var/log/daemon.log::sending attribute certificate issued by \"C=CH, O=Linux strongSwan, CN=expired AA\"::YES +dave::cat /var/log/daemon.log::received AUTHENTICATION_FAILED notify error::YES +carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES +dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::NO +moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES +moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES +moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::NO +moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::NO diff --git a/testing/tests/ikev2/acert-inline/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/acert-inline/hosts/carol/etc/ipsec.conf new file mode 100644 index 000000000..e72f78742 --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/carol/etc/ipsec.conf @@ -0,0 +1,20 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + +conn home + left=PH_IP_CAROL + leftcert=carolCert.pem + leftid=carol@strongswan.org + leftfirewall=yes + right=PH_IP_MOON + rightid=@moon.strongswan.org + rightsubnet=10.1.0.0/16 + keyexchange=ikev2 + auto=add diff --git a/testing/tests/ikev2/acert-inline/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem b/testing/tests/ikev2/acert-inline/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem new file mode 100644 index 000000000..a188a1d3d --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/carol/etc/ipsec.d/acerts/carol-sales.pem @@ -0,0 +1,18 @@ +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIIC7zCCAdcCAQEwgbCgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp +bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHaFe +pFwwWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP +BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZ6BG +MESkQjBAMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEW +MBQGA1UEAxMNc3Ryb25nU3dhbiBBQTANBgkqhkiG9w0BAQUFAAIIYO/yp98Yxu4w +IhgPMjAxNDAyMDcxMDAxNTdaGA8yMDIyMDQyNjEwMDE1N1owGTAXBggrBgEFBQcK +BDELMAkwBwwFc2FsZXMwfzByBgNVHSMEazBpCwHqxzoCXPi2xMHh2q7CV/ZSsLCh +SaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRsw +GQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCCBVOfhWvHBdhMAkGA1UdOAQCBQAw +DQYJKoZIhvcNAQEFBQADggEBAJA/duSysWae5X9JTC0BLY6gK8ggj5V9H3d60rM4 +7A8HVQldWe5QwYIRZmLS0XhMVHWiIvXJHwue2Xgs8DyAqILSCKIKpCJRhqPIxHCh +bek1nzw2YzVaU+E37He5V9PSkkRFO9tRvELhW3t4Wya7p4l6MVFW9ETOOtUqZYmt +bxAq/XEFZl/aFb2FW2RoKjUZpwxbrccCaV1hKIxtNen2ro31dNd9YHXe+fE4Fc7r +FTwbhOg3QLvZDXmiZt3LCXdMKAhayLbuSVsycuEtac44OVSvKhJ8GYykTRRn67nU +qCFNDe266KTNDqUMilrHm3FYGkpFtREOBajH4EqdMAJSdXg= +-----END ATTRIBUTE CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-inline/hosts/carol/etc/strongswan.conf b/testing/tests/ikev2/acert-inline/hosts/carol/etc/strongswan.conf new file mode 100644 index 000000000..dc937641c --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/carol/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown +} diff --git a/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.conf b/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.conf new file mode 100644 index 000000000..65c9819bb --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.conf @@ -0,0 +1,20 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + +conn home + left=PH_IP_DAVE + leftcert=daveCert.pem + leftid=dave@strongswan.org + leftfirewall=yes + right=PH_IP_MOON + rightid=@moon.strongswan.org + rightsubnet=10.1.0.0/16 + keyexchange=ikev2 + auto=add diff --git a/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-expired-aa.pem b/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-expired-aa.pem new file mode 100644 index 000000000..e612607aa --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-expired-aa.pem @@ -0,0 +1,18 @@ +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIIC7TCCAdUCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp +bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf +pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR +BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg +QzBBpD8wPTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x +EzARBgNVBAMTCmV4cGlyZWQgQUEwDQYJKoZIhvcNAQEFBQACCG25qKzXgZ9HMCIY +DzIwMTQwMjA3MTAxMzQyWhgPMjAyMjA0MjYxMDEzNDJaMBkwFwYIKwYBBQUHCgQx +CzAJMAcMBXNhbGVzMH8wcgYDVR0jBGswabOoTOBJ6lXcG4NAowI32Y/oXa9/oUmk +RzBFMQswCQYDVQQGEwJDSDEZMBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkG +A1UEAxMSc3Ryb25nU3dhbiBSb290IENBgggqIkNljRd9CTAJBgNVHTgEAgUAMA0G +CSqGSIb3DQEBBQUAA4IBAQCfX/84tHCidlVbOU4is/1hZc+FpK4GG1jcywM9mtjB +QUeX28LYkewDdRpe49zJuTbvuIIABTp+4alf/oo7sKLk+o2/qq6CPfx8BSRL1a61 +Y1wVeGmXqcRQgtX+r3asMtLBoAFO8VaHt6pY52bg2YMNVRrUnCUVLqQjT+/Ujr4f +Lhs74VOxn7S94YbqvP5rytNFjdzBREipmb8j4mhIyfwUluoWFCkzxuwRaSEGhSMO +NobJuj/mK0PUU+TMYEcOMpQ/nVyb9rBtOvDoNU3BeD+ovuamErT9/9vWhEOwMD4C +OeR+ofespDX+AdCyZ1Dr1GMyUmIRK7GERdasIhx5pYMk +-----END ATTRIBUTE CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-marketing.pem b/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-marketing.pem new file mode 100644 index 000000000..2f646c39d --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/dave/etc/ipsec.d/acerts/dave-marketing.pem @@ -0,0 +1,18 @@ +-----BEGIN ATTRIBUTE CERTIFICATE----- +MIIC9DCCAdwCAQEwgbGgTjBJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExp +bnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQQIBHKFf +pF0wWzELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xEzAR +BgNVBAsTCkFjY291bnRpbmcxHDAaBgNVBAMUE2RhdmVAc3Ryb25nc3dhbi5vcmeg +RjBEpEIwQDELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4x +FjAUBgNVBAMTDXN0cm9uZ1N3YW4gQUEwDQYJKoZIhvcNAQEFBQACCCPxWgWKmOUM +MCIYDzIwMTQwMjA3MDg1OTM3WhgPMjAyMjA0MjYwODU5MzdaMB0wGwYIKwYBBQUH +CgQxDzANMAsMCW1hcmtldGluZzB/MHIGA1UdIwRrMGkLAerHOgJc+LbEweHarsJX +9lKwsKFJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3 +YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIIFU5+Fa8cF2EwCQYDVR04 +BAIFADANBgkqhkiG9w0BAQUFAAOCAQEAThlKhGVv34sfnCSQn6nYUdxMhboTuC98 ++DgvTQ/tH0hddCJNg00SpO8AbStwEsqHFaSqFzAGHcMk+XUrBRSGszAwg8nKAKfT +MCvJbK6lWQcPF0WPSSk9/r1TLan4I9xhneNIIGQf1fnNo7NrQnmhJjolUgXQNwFA +qZgKBsk0jWcOSvI0bpK90km5flCHn/OA1rDCdaPuMwreDhvNDoApORYFPZVsLhid +CXSqT+FWfm2NfegS+Q4VHP3YLbY4vLepCerU9aMTUIPit0kf1N8piG/l6AUno1XP +VrcTvruQUWQb08H9aYt7l7kyhzOKkuXjVbdn5egZnK0m4WKmV50guA== +-----END ATTRIBUTE CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-inline/hosts/dave/etc/strongswan.conf b/testing/tests/ikev2/acert-inline/hosts/dave/etc/strongswan.conf new file mode 100644 index 000000000..dc937641c --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/dave/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac xcbc stroke kernel-netlink socket-default updown +} diff --git a/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.conf new file mode 100644 index 000000000..e3abea51f --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.conf @@ -0,0 +1,20 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + +conn rw + left=PH_IP_MOON + leftcert=moonCert.pem + leftid=@moon.strongswan.org + leftsubnet=10.1.0.0/16 + leftfirewall=yes + right=%any + rightgroups="finance, sales" + keyexchange=ikev2 + auto=add diff --git a/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa-expired.pem b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa-expired.pem new file mode 100644 index 000000000..20336fd79 --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa-expired.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDJzCCAg+gAwIBAgIIKiJDZY0XfQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE +BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u +Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDYwOTQ4NTJaFw0xNDAyMDcwOTQ4NTJaMD0x +CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRMwEQYDVQQD +EwpleHBpcmVkIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0s5R +X2Y9KUSoNewtwOhQunET9VRGrVYS+xDewmIuAHZt4jhbETSHS+r/qipV4mI+/orS +zma0+GVcDwbHRT3oDCrpG/DMpPznki+OzHT9e/HHk0yxb0Ti6vDDbZOM8y3r7ak0 +Dcq6BgGwPxwIW2u1YHRTj4yxlr5wj9iKU1SQGCwZIQZmjqrjoQlcrThIXju2bqN3 +SOjuaN6A2GAvcbb/IeQEm8HBqulmyBuGV7Gk9umG/nr61rulNxEp+3Dsce5mv7JR +dX5W8P6pv38A/f31Bh/EetEkv8qdnkH0aVAvd8Kb2yxc8Ofdu0kJNoPHGjrnSywl +kPh3z2pw6nOFpyFHoQIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2bbO1 +5eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAh9Sxryf5ip00ykCMStDYzQk27l4N +ncjU19RJqjrCuHupvWPJ+aYQFvssAnGGuK2rbw3rzVQba/Vn/o5d5wr1gxRtNQjv +z60jbqllmjF0TWvPf/CM/5LVAQJs2x5Mqtvy3pbNvetFHjZrzVDobdVJpqzaZGnh +oP0+HUMdE+fyLa0LfaRKYNv7r/vxvzsHZvgJawHK1b/2VWtrkIMyhAgHYViih06j +2bfVI/f5tk7/UljzLOCB22IFIn05wh4jyKq6az7B2Xu1Kk0/eA12eRqG134P8OYe +hAPcuj4QEDwV0ESw5cueD2I0MxbXuH2vBG5ziSBfw2Phj7f9iYurmMsZew== +-----END CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa.pem b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa.pem new file mode 100644 index 000000000..fbfa7ee8b --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/aacerts/aa.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDKjCCAhKgAwIBAgIIFU5+Fa8cF2EwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UE +BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9u +Z1N3YW4gUm9vdCBDQTAeFw0xNDAyMDcwODUwMzVaFw0yMjA0MjYwODUwMzVaMEAx +CzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2FuMRYwFAYDVQQD +Ew1zdHJvbmdTd2FuIEFBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +y6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTFFbSbpQJxWk603BJH +hlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsAQ3yWfkZZK1jxTdTP +dvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqYzdWFCUINTXUGEr/L +lt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNTjS2xaaklUCq2auR/ +QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf+7suyGczSRMP6+5N +jqNqab7l/SHwHQMVEE5ihwIDAQABoyMwITAfBgNVHSMEGDAWgBRdp91wBlEyfue2 +bbO15eBg6i5N7zANBgkqhkiG9w0BAQUFAAOCAQEAakPgMKVjkQmpI1VROcetvZzM +ZHMWwdu9IcwNpi/8qs2qNh6wCYv9c4V6O4zRCB1u8TuAIQiwLNZgjk+OKKLzvUik +gBRogn/apXsvAtfu9ODv5GuS6F38OYWDu/c3fiCZB2MKTtmEro2EkxxMw4DkfJ02 +R/xrhAnjeQlRQOChgQ3fHNmH9gVNaKXNq+JaoU2TfHFwuYMMe6q1L+vhOaBd58YA +6wPHOOLcIEaebHIqa4duAE5txJsZCEEySrr5stqo4j7929BAw+U6f+6Wb+UAEW6g +91PKAl5QVbAzgPFWoPkOTNdDOprT+B4eGx0EC2QTEtxxDv5589choF7BMRCzsQ== +-----END CERTIFICATE----- diff --git a/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa-expired.pem b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa-expired.pem new file mode 100644 index 000000000..0e694c4f1 --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa-expired.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA0s5RX2Y9KUSoNewtwOhQunET9VRGrVYS+xDewmIuAHZt4jhb +ETSHS+r/qipV4mI+/orSzma0+GVcDwbHRT3oDCrpG/DMpPznki+OzHT9e/HHk0yx +b0Ti6vDDbZOM8y3r7ak0Dcq6BgGwPxwIW2u1YHRTj4yxlr5wj9iKU1SQGCwZIQZm +jqrjoQlcrThIXju2bqN3SOjuaN6A2GAvcbb/IeQEm8HBqulmyBuGV7Gk9umG/nr6 +1rulNxEp+3Dsce5mv7JRdX5W8P6pv38A/f31Bh/EetEkv8qdnkH0aVAvd8Kb2yxc +8Ofdu0kJNoPHGjrnSywlkPh3z2pw6nOFpyFHoQIDAQABAoIBAQCRRwiDM2VhBGTc +THi3oiLIaldz0fGnUVNhXR33XkwPm45cwbPY5pd7NWeecPChRE3fg/KFtfhv2wKX +hHdd+6zofcYKsGeIKJa6gzXpJ5LtkRGWLNt3MEUl3mkAIhiYGoSmU96Axr5ul0lM +JNiJkG/+GgzgN/jHR1UxfOzPQs7PKIyzCE2N0v8dRxHWeyPCRxSavlhAoQKjWxCe +FfVBzLi+L1faidcwf4GWyeTfhvALXQnQGgVPH6PX0z3mwaeYHPWVXWJGcaF0bi3H +HaEb2YexTDkEVU0PUVYO40OgtmKVLmi5t+ZP+/dFasy9elzgM3sSmVc7IBp6BBCH +NgUcWcf1AoGBAOiti9raozwdA/wHAMaCCbgXq8Dg0+3LYnb0ob7w8OaHRl4Mvpup +7MtxPGmr9IOddf8/49+L9STsioMllGt0TrkMrlKyg/eglGMalvbJmUYw1kERtQZw +0CYYE8DXR3fvN+eMl1maZ4Wf048UugWQhsRGzOyUKcMXhAlIXwTevnCfAoGBAOfv +isxrw5vttRxfszZaWeomos9bk6NA9FJYG1rS6ocR+Ww2OpQSJVTmbjpYv1lTb9yr +PvcZtPbWP/6g8kjPTQQ+ZnJQB4RpWek0KlxwxC6JW5HzqMJFn68zX4/jE5kXqVow +Y+Sfgrkr4QXX8vjzp9GFRhAW6bA5DlswqH7XmB+/AoGARHYDx3I7Q026RWZ+GOpc +F7mHRKoiUT5di2ixSrA0AXBeCQAw+TZHQRjhUKpSuIMVG/RdhQH2MFYU7z+YawF+ +xD3x8M0rvSmXX42MS7LHkXp/IAgovmtlI0BEV6JAGg7d4Rhh0/B1c0Cyi8/qaAa9 +UHUQiK+Tlh6OL/kGVDWBzTsCgYBTW5Jk+e4pontPIU4FoN9j+lLVd7JOIFAvMB9U +uy0zMlCUhcDz6rmkE9VV/wN2lThE9P8CTCjv9fy2BR5O8MJbXhnvx7eL7Vk1KVx4 +MMcxeoiAojPq7p7/ltUnn5MxmIFzOqUMTA/tgUm0kfJvaxLLiLyvl6yRe1AfkhNc +0xuHfQKBgQCyQEcvtmR1Qx82ob5uTvBbKFDbSniiJMi9kgMk266PNRdg85Q4RC7X +j5KNALOb5u2oMT6/Hzi4KruDBc/6viXRuMYM+L1JIy8y6wcVjCQetxyUIGgc9Ouh +59bOkD+SOth52Y+AYFyCaJOSoTFHlTcLwCvk9gVdbgVYJi7/jyohSQ== +-----END RSA PRIVATE KEY----- diff --git a/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa.pem b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa.pem new file mode 100644 index 000000000..a4e001791 --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/moon/etc/ipsec.d/private/aa.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAy6nSTRzCuTbfuv2FwnXC/R7+5L5WViVxBfCEkaxzW5GJJGTF +FbSbpQJxWk603BJHhlVAVj8jUNMKcOuj/l8UPNV8lcDslQfe/AZd6gqdCwP7uMsA +Q3yWfkZZK1jxTdTPdvcpLNozt7hmIroJVTGzmzI5YIvWbYT/zyEge6pEPaXr8IqY +zdWFCUINTXUGEr/Llt3IUKMTNnhabPHAbTIZ3i0c98Ci0ZzZjGx+JmVVvcY9lgNT +jS2xaaklUCq2auR/QzP7PxuSYkAF4qYhG7Ujeo7v4z79mXISFTlyqKe7k18wUKdf ++7suyGczSRMP6+5NjqNqab7l/SHwHQMVEE5ihwIDAQABAoIBAQCIvn5QfkYUG87+ +eyirV2xTjdMw/Md1UfBgP4yTTsmpqr79K5fUqg5zLX+0VfJDbRaPEICBKCVrKDfz +d5QFwAsTiXf8CKwQqFdEunWmJfgppEQIYGzN40IciNloLHDghEnEI9GGpv9glLQn +DugjRprEUmWJ+HpB0LH9fc2Ums704Fcd8ud3bStCRxU1TA5VGBHmnyK5/n1Lb1oB +01LoW8ins8lATuV+MAaWZgmCbPajfXY9wQGq3IDMVlOUOTxRo742T1GTrwBZR8ot +mgs/Gs1XkJRC1x9Z9Z1Cej1iC5llv0zX8AUdejczGHQGHj1a1Dg8FpRneW6rrLyK +vvKR8jtRAoGBAOpyk63yCPM2LqU4US5aHXPoLyyGeo4v7okTKIuoUfosQ4XJvylM +lEYoFVFKYBKcXRQhmeWyILtto2BBDnG1HWAi1MbUWLxDNEYieurzJiv4i0XbR6cH +mLhMMlQyKmwLRF5v3EiupjKBZRk2iYcx4eeL3gsUWUzRPeWJHKDgYF4PAoGBAN5i +xyOsU/32gQ6vLQxt8us6n3OBr1PiFg8JIdADPnKOCxJ5uS8dkqOQHCMKyvS9MWrf +3Wj4MOBEgW7fBBAxkvjJdPhBW70/pGM46mb991dTHJ4gIAzGxgvJIqw/FjqEC7Oo +vWDRS4dxW56Rs2tdLn2GRvvlS3+3z90twqS/t6wJAoGBAJpzhzT2Gc1YaZxxIJI/ +zd15HfLgWUbo7uWhGHoBFpiQpp8yDNzBVYFukLSwIeDA4FUN2dxH4GZ50ULtOP3S +Cps19yVR6W+Fep+lwYKdUw1uvRn1Xxv71jG8CQAM2IO7XHw2h1HetSDau+bDVhEZ +3LB1JX/5FOeVhYh9Lr4Rc4sjAoGBAJCTCv+oEtqyHOjc/Z5tBFXkwLCpCMCx5MFV +oIPI+BolOhGCzN9SjHiFQaWOaK9/J9dhPmH1qGDEaJkZp1yXvgK7ha23X9rCuy4+ +XDUkul4tDBfIrs1flHUpB7+PK/ZSzgC4nJWKu12MVpHaCxirdYPpfdBZGyIm753N +GBNfCBtxAoGAKkrHlsfq7GVVU7Jj1AlNCwmlm21vSJ45G3cNR1GpgdplB5JR1ldV +2kxA4xm8uFVIJ60OQ9VZ5Svaovqh8iX2sndSOZMefjH3qiDu/4mJqRA3xV5ugon3 +RAzinJzUU4tnk9pajOMD3FHOHvUO4hAJjVYEzqLIIRE7QhPuEpLevZ4= +-----END RSA PRIVATE KEY----- diff --git a/testing/tests/ikev2/acert-inline/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/acert-inline/hosts/moon/etc/strongswan.conf new file mode 100644 index 000000000..cd836a2b7 --- /dev/null +++ b/testing/tests/ikev2/acert-inline/hosts/moon/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation acert hmac xcbc stroke kernel-netlink socket-default updown +} diff --git a/testing/tests/ikev2/acert-inline/posttest.dat b/testing/tests/ikev2/acert-inline/posttest.dat new file mode 100644 index 000000000..a0ef98440 --- /dev/null +++ b/testing/tests/ikev2/acert-inline/posttest.dat @@ -0,0 +1,13 @@ +moon::ipsec stop +carol::ipsec stop +dave::ipsec stop +moon::iptables-restore < /etc/iptables.flush +carol::iptables-restore < /etc/iptables.flush +dave::iptables-restore < /etc/iptables.flush +carol::rm /etc/ipsec.d/acerts/carol-sales.pem +dave::rm /etc/ipsec.d/acerts/dave-expired-aa.pem +dave::rm /etc/ipsec.d/acerts/dave-marketing.pem +moon::rm /etc/ipsec.d/private/aa-expired.pem +moon::rm /etc/ipsec.d/private/aa.pem +moon::rm /etc/ipsec.d/aacerts/aa-expired.pem +moon::rm /etc/ipsec.d/aacerts/aa.pem diff --git a/testing/tests/ikev2/acert-inline/pretest.dat b/testing/tests/ikev2/acert-inline/pretest.dat new file mode 100644 index 000000000..8bbea1412 --- /dev/null +++ b/testing/tests/ikev2/acert-inline/pretest.dat @@ -0,0 +1,9 @@ +moon::iptables-restore < /etc/iptables.rules +carol::iptables-restore < /etc/iptables.rules +dave::iptables-restore < /etc/iptables.rules +moon::ipsec start +carol::ipsec start +dave::ipsec start +carol::sleep 1 +carol::ipsec up home +dave::ipsec up home diff --git a/testing/tests/ikev2/acert-inline/test.conf b/testing/tests/ikev2/acert-inline/test.conf new file mode 100644 index 000000000..f29298850 --- /dev/null +++ b/testing/tests/ikev2/acert-inline/test.conf @@ -0,0 +1,21 @@ +#!/bin/bash +# +# This configuration file provides information on the +# guest instances used for this test + +# All guest instances that are required for this test +# +VIRTHOSTS="alice moon carol winnetou dave" + +# Corresponding block diagram +# +DIAGRAM="a-m-c-w-d.png" + +# Guest instances on which tcpdump is to be started +# +TCPDUMPHOSTS="moon" + +# Guest instances on which IPsec is started +# Used for IPsec logging purposes +# +IPSECHOSTS="moon carol dave"