From 6ecf1aab35dbf8d7c245935558570295a0352c83 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 29 Aug 2013 09:04:36 +0200 Subject: [PATCH 1/9] unbound: Add support for DLV (DNSSEC Lookaside Validation) Fixes #392. --- man/strongswan.conf.5.in | 10 +++++- .../plugins/unbound/unbound_resolver.c | 35 ++++++++++++------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/man/strongswan.conf.5.in b/man/strongswan.conf.5.in index e8dbe63f8..0fb239adc 100644 --- a/man/strongswan.conf.5.in +++ b/man/strongswan.conf.5.in @@ -886,7 +886,15 @@ File to read pseudo random bytes from, instead of @urandom_device@ File to read DNS resolver configuration from .TP .BR libstrongswan.plugins.unbound.trust_anchors " [/etc/ipsec.d/dnssec.keys]" -File to read DNSSEC trust anchors from (usually root zone KSK) +File to read DNSSEC trust anchors from (usually root zone KSK). The format of +the file is the standard DNS Zone file format, anchors can be stored as DS or +DNSKEY entries in the file. +.TP +.BR libstrongswan.plugins.unbound.dlv_anchors +File to read trusted keys for DLV (DNSSEC Lookaside Validation) from. It uses +the same format as \fItrust_anchors\fR. Only one DLV can be configured, which +is then used as a root trusted DLV, this means that it is a lookaside for +the root. .SS libtls section .TP .BR libtls.cipher diff --git a/src/libstrongswan/plugins/unbound/unbound_resolver.c b/src/libstrongswan/plugins/unbound/unbound_resolver.c index 44a2c764b..42cdbc6cc 100644 --- a/src/libstrongswan/plugins/unbound/unbound_resolver.c +++ b/src/libstrongswan/plugins/unbound/unbound_resolver.c @@ -94,16 +94,17 @@ resolver_t *unbound_resolver_create(void) { private_resolver_t *this; int ub_retval = 0; - char *resolv_conf_file; - char *trust_anchor_file; + char *resolv_conf, *trust_anchors, *dlv_anchors; - resolv_conf_file = lib->settings->get_str(lib->settings, + resolv_conf = lib->settings->get_str(lib->settings, "libstrongswan.plugins.unbound.resolv_conf", RESOLV_CONF_FILE); - - trust_anchor_file = lib->settings->get_str(lib->settings, + trust_anchors = lib->settings->get_str(lib->settings, "libstrongswan.plugins.unbound.trust_anchors", TRUST_ANCHOR_FILE); + dlv_anchors = lib->settings->get_str(lib->settings, + "libstrongswan.plugins.unbound.dlv_anchors", + NULL); INIT(this, .public = { @@ -120,24 +121,34 @@ resolver_t *unbound_resolver_create(void) return NULL; } - DBG1(DBG_CFG, "loading unbound resolver config from '%s'", resolv_conf_file); - ub_retval = ub_ctx_resolvconf(this->ctx, resolv_conf_file); + DBG2(DBG_CFG, "loading unbound resolver config from '%s'", resolv_conf); + ub_retval = ub_ctx_resolvconf(this->ctx, resolv_conf); if (ub_retval) { DBG1(DBG_CFG, "failed to read the resolver config: %s (%s)", - ub_strerror(ub_retval), strerror(errno)); + ub_strerror(ub_retval), strerror(errno)); destroy(this); return NULL; } - DBG1(DBG_CFG, "loading unbound trust anchors from '%s'", trust_anchor_file); - ub_retval = ub_ctx_add_ta_file(this->ctx, trust_anchor_file); + DBG2(DBG_CFG, "loading unbound trust anchors from '%s'", trust_anchors); + ub_retval = ub_ctx_add_ta_file(this->ctx, trust_anchors); if (ub_retval) { DBG1(DBG_CFG, "failed to load trust anchors: %s (%s)", - ub_strerror(ub_retval), strerror(errno)); + ub_strerror(ub_retval), strerror(errno)); } + if (dlv_anchors) + { + DBG2(DBG_CFG, "loading trusted keys for DLV from '%s'", dlv_anchors); + ub_retval = ub_ctx_set_option(this->ctx, "dlv-anchor-file:", + dlv_anchors); + if (ub_retval) + { + DBG1(DBG_CFG, "failed to load trusted keys for DLV: %s (%s)", + ub_strerror(ub_retval), strerror(errno)); + } + } return &this->public; } - From de5ea570f1c47244f21d8200737f2154648752ce Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 29 Aug 2013 15:25:23 +0200 Subject: [PATCH 2/9] ipseckey: Depend on plugin features to create public key and certificate objects --- src/libcharon/plugins/ipseckey/ipseckey_plugin.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcharon/plugins/ipseckey/ipseckey_plugin.c b/src/libcharon/plugins/ipseckey/ipseckey_plugin.c index 2fd820f94..9bc49ba28 100644 --- a/src/libcharon/plugins/ipseckey/ipseckey_plugin.c +++ b/src/libcharon/plugins/ipseckey/ipseckey_plugin.c @@ -109,6 +109,8 @@ METHOD(plugin_t, get_features, int, PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), PLUGIN_PROVIDE(CUSTOM, "ipseckey"), PLUGIN_DEPENDS(RESOLVER), + PLUGIN_DEPENDS(PUBKEY, KEY_RSA), + PLUGIN_DEPENDS(CERT_ENCODE, CERT_TRUSTED_PUBKEY), }; *features = f; return countof(f); From e8130a94981744c0e3ceb8ea1d4599cd2838e444 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 29 Aug 2013 15:47:05 +0200 Subject: [PATCH 3/9] ipseckey: Refactor creation of certificate enumerator Reduces nesting and fixes a memory leak (rrsig_enum). --- .../plugins/ipseckey/ipseckey_cred.c | 177 +++++++++--------- 1 file changed, 86 insertions(+), 91 deletions(-) diff --git a/src/libcharon/plugins/ipseckey/ipseckey_cred.c b/src/libcharon/plugins/ipseckey/ipseckey_cred.c index e8722f12c..e97a88281 100644 --- a/src/libcharon/plugins/ipseckey/ipseckey_cred.c +++ b/src/libcharon/plugins/ipseckey/ipseckey_cred.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Tobias Brunner * Copyright (C) 2012 Reto Guadagnini * Hochschule fuer Technik Rapperswil * @@ -12,6 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ + #define _GNU_SOURCE #include #include @@ -20,7 +22,6 @@ #include "ipseckey.h" #include -#include typedef struct private_ipseckey_cred_t private_ipseckey_cred_t; @@ -84,7 +85,7 @@ METHOD(enumerator_t, cert_enumerator_enumerate, bool, if (cur_ipseckey && cur_ipseckey->get_algorithm(cur_ipseckey) != IPSECKEY_ALGORITHM_RSA) { - DBG1(DBG_CFG, "unsupported ipseckey algorithm -skipping this key"); + DBG1(DBG_CFG, "unsupported ipseckey algorithm - skipping this key"); cur_ipseckey->destroy(cur_ipseckey); supported_ipseckey_found = FALSE; } @@ -134,101 +135,95 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, private_ipseckey_cred_t *this, certificate_type_t cert, key_type_t key, identification_t *id, bool trusted) { - char *fqdn = NULL; - resolver_response_t *response = NULL; - rr_set_t *rrset = NULL; - enumerator_t *rrsig_enum = NULL; - rr_t *rrsig = NULL; - bio_reader_t *reader = NULL; - chunk_t ignore; - u_int32_t nBefore, nAfter; + resolver_response_t *response; + enumerator_t *rrsig_enum; cert_enumerator_t *e; + rr_set_t *rrset; + rr_t *rrsig; + bio_reader_t *reader; + u_int32_t nBefore, nAfter; + chunk_t ignore; + char *fqdn; - if (id && id->get_type(id) == ID_FQDN) + if (!id || id->get_type(id) != ID_FQDN) { - /** Query the DNS for the required IPSECKEY RRs */ - - if (0 >= asprintf(&fqdn, "%Y", id)) - { - DBG1(DBG_CFG, "empty FQDN string"); - return enumerator_create_empty(); - } - - DBG1(DBG_CFG, "performing a DNS query for IPSECKEY RRs of '%s'", - fqdn); - response = this->res->query(this->res, fqdn, RR_CLASS_IN, - RR_TYPE_IPSECKEY); - if (!response) - { - DBG1(DBG_CFG, " query for IPSECKEY RRs failed"); - free(fqdn); - return enumerator_create_empty(); - } - - if (!response->has_data(response) || - !response->query_name_exist(response)) - { - DBG1(DBG_CFG, " unable to retrieve IPSECKEY RRs from the DNS"); - response->destroy(response); - free(fqdn); - return enumerator_create_empty(); - } - - if (!(response->get_security_state(response) == SECURE)) - { - DBG1(DBG_CFG, " DNSSEC state of IPSECKEY RRs is not secure"); - response->destroy(response); - free(fqdn); - return enumerator_create_empty(); - } - - free(fqdn); - - /** Determine the validity period of the retrieved IPSECKEYs - * - * We use the "Signature Inception" and "Signature Expiration" field - * of the first RRSIG RR to determine the validity period of the - * IPSECKEY RRs. TODO: Take multiple RRSIGs into account. - */ - rrset = response->get_rr_set(response); - rrsig_enum = rrset->create_rrsig_enumerator(rrset); - if (!rrsig_enum || !rrsig_enum->enumerate(rrsig_enum, &rrsig)) - { - DBG1(DBG_CFG, " unable to determine the validity period of " - "IPSECKEY RRs because no RRSIGs are present"); - DESTROY_IF(rrsig_enum); - response->destroy(response); - return enumerator_create_empty(); - } - - /** - * Parse the RRSIG for its validity period (RFC 4034) - */ - reader = bio_reader_create(rrsig->get_rdata(rrsig)); - reader->read_data(reader, 8, &ignore); - reader->read_uint32(reader, &nAfter); - reader->read_uint32(reader, &nBefore); - reader->destroy(reader); - - /*Create and return an iterator over the retrieved IPSECKEYs */ - INIT(e, - .public = { - .enumerate = (void*)_cert_enumerator_enumerate, - .destroy = _cert_enumerator_destroy, - }, - .inner = response->get_rr_set(response)->create_rr_enumerator( - response->get_rr_set(response)), - .response = response, - .notBefore = nBefore, - .notAfter = nAfter, - .identity = id, - ); - - return &e->public; + return enumerator_create_empty(); } + /* query the DNS for the required IPSECKEY RRs */ + if (asprintf(&fqdn, "%Y", id) <= 0) + { + DBG1(DBG_CFG, "failed to determine FQDN to retrieve IPSECKEY RRs"); + return enumerator_create_empty(); + } + DBG1(DBG_CFG, "performing a DNS query for IPSECKEY RRs of '%s'", fqdn); + response = this->res->query(this->res, fqdn, RR_CLASS_IN, RR_TYPE_IPSECKEY); + if (!response) + { + DBG1(DBG_CFG, " query for IPSECKEY RRs failed"); + free(fqdn); + return enumerator_create_empty(); + } + free(fqdn); - return enumerator_create_empty(); + if (!response->has_data(response) || + !response->query_name_exist(response)) + { + DBG1(DBG_CFG, " unable to retrieve IPSECKEY RRs from the DNS"); + response->destroy(response); + return enumerator_create_empty(); + } + + if (response->get_security_state(response) != SECURE) + { + DBG1(DBG_CFG, " DNSSEC state of IPSECKEY RRs is not secure"); + response->destroy(response); + return enumerator_create_empty(); + } + + /* determine the validity period of the retrieved IPSECKEYs + * + * we use the "Signature Inception" and "Signature Expiration" field + * of the first RRSIG RR to determine the validity period of the + * IPSECKEY RRs. + * TODO: Take multiple RRSIGs into account. */ + rrset = response->get_rr_set(response); + rrsig_enum = rrset->create_rrsig_enumerator(rrset); + if (!rrsig_enum || !rrsig_enum->enumerate(rrsig_enum, &rrsig)) + { + DBG1(DBG_CFG, " unable to determine the validity period of " + "IPSECKEY RRs because no RRSIGs are present"); + DESTROY_IF(rrsig_enum); + response->destroy(response); + return enumerator_create_empty(); + } + rrsig_enum->destroy(rrsig_enum); + + /* parse the RRSIG for its validity period (RFC 4034) */ + reader = bio_reader_create(rrsig->get_rdata(rrsig)); + if (!reader->read_data(reader, 8, &ignore) || + !reader->read_uint32(reader, &nAfter) || + !reader->read_uint32(reader, &nBefore)) + { + DBG1(DBG_CFG, " unable to determine the validity period of RRSIG RRs"); + reader->destroy(reader); + response->destroy(response); + return enumerator_create_empty(); + } + reader->destroy(reader); + + INIT(e, + .public = { + .enumerate = (void*)_cert_enumerator_enumerate, + .destroy = _cert_enumerator_destroy, + }, + .inner = rrset->create_rr_enumerator(rrset), + .response = response, + .notBefore = nBefore, + .notAfter = nAfter, + .identity = id, + ); + return &e->public; } METHOD(ipseckey_cred_t, destroy, void, From 8ac54970f5f97204c7470b74a7843c00141bb76a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 29 Aug 2013 15:58:48 +0200 Subject: [PATCH 4/9] ipseckey: Properly handle failure to create a certificate Also, try the next key (if available) if parsing an IPSECKEY failed. --- .../plugins/ipseckey/ipseckey_cred.c | 61 +++++++++---------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/src/libcharon/plugins/ipseckey/ipseckey_cred.c b/src/libcharon/plugins/ipseckey/ipseckey_cred.c index e97a88281..3ff6dd87d 100644 --- a/src/libcharon/plugins/ipseckey/ipseckey_cred.c +++ b/src/libcharon/plugins/ipseckey/ipseckey_cred.c @@ -62,64 +62,59 @@ typedef struct { METHOD(enumerator_t, cert_enumerator_enumerate, bool, cert_enumerator_t *this, certificate_t **cert) { - rr_t *cur_rr = NULL; - ipseckey_t *cur_ipseckey = NULL; - chunk_t pub_key; - public_key_t * key = NULL; - bool supported_ipseckey_found = FALSE; + ipseckey_t *cur_ipseckey; + public_key_t *public; + rr_t *cur_rr; + chunk_t key; /* Get the next supported IPSECKEY using the inner enumerator. */ - while (this->inner->enumerate(this->inner, &cur_rr) && - !supported_ipseckey_found) + while (this->inner->enumerate(this->inner, &cur_rr)) { - supported_ipseckey_found = TRUE; - cur_ipseckey = ipseckey_create_frm_rr(cur_rr); if (!cur_ipseckey) { - DBG1(DBG_CFG, "failed to parse ipseckey - skipping this key"); - supported_ipseckey_found = FALSE; + DBG1(DBG_CFG, " failed to parse IPSECKEY, skipping"); + continue; } - if (cur_ipseckey && - cur_ipseckey->get_algorithm(cur_ipseckey) != IPSECKEY_ALGORITHM_RSA) + if (cur_ipseckey->get_algorithm(cur_ipseckey) != IPSECKEY_ALGORITHM_RSA) { - DBG1(DBG_CFG, "unsupported ipseckey algorithm - skipping this key"); + DBG1(DBG_CFG, " unsupported IPSECKEY algorithm, skipping"); cur_ipseckey->destroy(cur_ipseckey); - supported_ipseckey_found = FALSE; + continue; } - } - if (supported_ipseckey_found) - { - /* - * Wrap the key of the IPSECKEY in a certificate and return this - * certificate. - */ - pub_key = cur_ipseckey->get_public_key(cur_ipseckey); - - key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, - BUILD_BLOB_DNSKEY, pub_key, - BUILD_END); - - if (!key) + /* wrap the key of the IPSECKEY in a certificate and return this + * certificate */ + key = cur_ipseckey->get_public_key(cur_ipseckey); + public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, + BUILD_BLOB_DNSKEY, key, + BUILD_END); + if (!public) { - DBG1(DBG_CFG, "failed to create public key from ipseckey"); + DBG1(DBG_CFG, " failed to create public key from IPSECKEY"); cur_ipseckey->destroy(cur_ipseckey); - return FALSE; + continue; } *cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_TRUSTED_PUBKEY, - BUILD_PUBLIC_KEY, key, + BUILD_PUBLIC_KEY, public, BUILD_SUBJECT, this->identity, BUILD_NOT_BEFORE_TIME, this->notBefore, BUILD_NOT_AFTER_TIME, this->notAfter, BUILD_END); + if (*cert == NULL) + { + DBG1(DBG_CFG, " failed to create certificate from IPSECKEY"); + cur_ipseckey->destroy(cur_ipseckey); + public->destroy(public); + continue; + } + cur_ipseckey->destroy(cur_ipseckey); return TRUE; } - return FALSE; } From b638c131de07dc78de0877de41ad02ce32e6624c Mon Sep 17 00:00:00 2001 From: "Ruslan N. Marchenko" Date: Fri, 30 Aug 2013 17:51:12 +0200 Subject: [PATCH 5/9] dnscert: Add DNS CERT support for pubkey authentication Add DNSSEC protected CERT RR delivered certificate authentication. The new dnscert plugin is based on the ipseckey plugin and relies on the existing PEM decoder as well as x509 and PGP parsers. As such the plugin expects PEM encoded PKIX(x509) or PGP(GPG) certificate payloads. The plugin is targeted to improve interoperability with Racoon, which supports this type of authentication, ignoring in-stream certificates and using only DNS provided certificates for FQDN IDs. --- configure.ac | 4 + src/libcharon/Makefile.am | 7 + src/libcharon/plugins/dnscert/Makefile.am | 20 ++ src/libcharon/plugins/dnscert/dnscert.c | 142 ++++++++++++ src/libcharon/plugins/dnscert/dnscert.h | 161 +++++++++++++ src/libcharon/plugins/dnscert/dnscert_cred.c | 214 ++++++++++++++++++ src/libcharon/plugins/dnscert/dnscert_cred.h | 63 ++++++ .../plugins/dnscert/dnscert_plugin.c | 166 ++++++++++++++ .../plugins/dnscert/dnscert_plugin.h | 55 +++++ 9 files changed, 832 insertions(+) create mode 100644 src/libcharon/plugins/dnscert/Makefile.am create mode 100644 src/libcharon/plugins/dnscert/dnscert.c create mode 100644 src/libcharon/plugins/dnscert/dnscert.h create mode 100644 src/libcharon/plugins/dnscert/dnscert_cred.c create mode 100644 src/libcharon/plugins/dnscert/dnscert_cred.h create mode 100644 src/libcharon/plugins/dnscert/dnscert_plugin.c create mode 100644 src/libcharon/plugins/dnscert/dnscert_plugin.h diff --git a/configure.ac b/configure.ac index 66cbfa987..82c530424 100644 --- a/configure.ac +++ b/configure.ac @@ -136,6 +136,7 @@ ARG_DISBL_SET([pkcs12], [disable PKCS12 container support plugin.]) ARG_DISBL_SET([pgp], [disable PGP key decoding plugin.]) ARG_DISBL_SET([dnskey], [disable DNS RR key decoding plugin.]) ARG_DISBL_SET([sshkey], [disable SSH key decoding plugin.]) +ARG_ENABL_SET([dnscert], [enable DNSCERT authentication plugin.]) ARG_ENABL_SET([ipseckey], [enable IPSECKEY authentication plugin.]) ARG_DISBL_SET([pem], [disable PEM decoding plugin.]) ARG_DISBL_SET([hmac], [disable HMAC crypto implementation plugin.]) @@ -1015,6 +1016,7 @@ 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([padlock], [s charon]) @@ -1181,6 +1183,7 @@ AM_CONDITIONAL(USE_ANDROID_LOG, test x$android_log = xtrue) AM_CONDITIONAL(USE_MAEMO, test x$maemo = xtrue) AM_CONDITIONAL(USE_SMP, test x$smp = xtrue) AM_CONDITIONAL(USE_SQL, test x$sql = xtrue) +AM_CONDITIONAL(USE_DNSCERT, test x$dnscert = xtrue) AM_CONDITIONAL(USE_IPSECKEY, test x$ipseckey = xtrue) AM_CONDITIONAL(USE_UPDOWN, test x$updown = xtrue) AM_CONDITIONAL(USE_DHCP, test x$dhcp = xtrue) @@ -1442,6 +1445,7 @@ AC_CONFIG_FILES([ src/libcharon/plugins/farp/Makefile src/libcharon/plugins/smp/Makefile src/libcharon/plugins/sql/Makefile + src/libcharon/plugins/dnscert/Makefile src/libcharon/plugins/ipseckey/Makefile src/libcharon/plugins/medsrv/Makefile src/libcharon/plugins/medcli/Makefile diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 5ee047b9c..df58eaa10 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -216,6 +216,13 @@ if MONOLITHIC endif endif +if USE_DNSCERT + SUBDIRS += plugins/dnscert +if MONOLITHIC + libcharon_la_LIBADD += plugins/dnscert/libstrongswan-dnscert.la +endif +endif + if USE_IPSECKEY SUBDIRS += plugins/ipseckey if MONOLITHIC diff --git a/src/libcharon/plugins/dnscert/Makefile.am b/src/libcharon/plugins/dnscert/Makefile.am new file mode 100644 index 000000000..51d542b30 --- /dev/null +++ b/src/libcharon/plugins/dnscert/Makefile.am @@ -0,0 +1,20 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-dnscert.la +else +plugin_LTLIBRARIES = libstrongswan-dnscert.la +endif + +libstrongswan_dnscert_la_SOURCES = \ + dnscert_plugin.h dnscert_plugin.c \ + dnscert_cred.h dnscert_cred.c \ + dnscert.h dnscert.c + +libstrongswan_dnscert_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/dnscert/dnscert.c b/src/libcharon/plugins/dnscert/dnscert.c new file mode 100644 index 000000000..882ad9f0c --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "dnscert.h" + +#include +#include +#include + +typedef struct private_dnscert_t private_dnscert_t; + +/** +* private data of the dnscert +*/ +struct private_dnscert_t { + + /** + * public functions + */ + dnscert_t public; + + /** + * Certificate type + */ + u_int16_t cert_type; + + /** + * Key tag + */ + u_int16_t key_tag; + + /** + * Algorithm + */ + u_int8_t algorithm; + + /** + * Certificate + */ + chunk_t certificate; +}; + +METHOD(dnscert_t, get_cert_type, dnscert_type_t, + private_dnscert_t *this) +{ + return this->cert_type; +} + +METHOD(dnscert_t, get_key_tag, u_int16_t, + private_dnscert_t *this) +{ + return this->key_tag; +} + +METHOD(dnscert_t, get_algorithm, dnscert_algorithm_t, + private_dnscert_t *this) +{ + return this->algorithm; +} + +METHOD(dnscert_t, get_certificate, chunk_t, + private_dnscert_t *this) +{ + return this->certificate; +} + +METHOD(dnscert_t, destroy, void, + private_dnscert_t *this) +{ + chunk_free(&this->certificate); + free(this); +} + +dnscert_t *dnscert_create_frm_rr(rr_t *rr) +{ + private_dnscert_t *this; + bio_reader_t *reader = NULL; + + INIT(this, + .public = { + .get_cert_type = _get_cert_type, + .get_key_tag = _get_key_tag, + .get_algorithm = _get_algorithm, + .get_certificate = _get_certificate, + .destroy = _destroy, + }, + ); + + if (rr->get_type(rr) != RR_TYPE_CERT) + { + DBG1(DBG_CFG, "unable to create a dnscert out of an RR " + "whose type is not CERT"); + free(this); + return NULL; + } + + /** + * Parse the content (RDATA field) of the RR + * First - type/tag/algo fields and then cert body + */ + reader = bio_reader_create(rr->get_rdata(rr)); + if (!reader->read_uint16(reader, &this->cert_type) || + !reader->read_uint16(reader, &this->key_tag) || + !reader->read_uint8(reader, &this->algorithm) ) + { + DBG1(DBG_CFG, "CERT RR has a wrong format"); + reader->destroy(reader); + free(this); + return NULL; + } + + if (!reader->read_data(reader, reader->remaining(reader), + &this->certificate)) + { + DBG1(DBG_CFG, "failed to read DNS certificate field"); + reader->destroy(reader); + free(this); + return NULL; + } + this->certificate = chunk_clone(this->certificate); + reader->destroy(reader); + return &this->public; +} diff --git a/src/libcharon/plugins/dnscert/dnscert.h b/src/libcharon/plugins/dnscert/dnscert.h new file mode 100644 index 000000000..f93263fd6 --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert.h @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup dnscert_i dnscert + * @{ @ingroup dnscert + */ + +#ifndef DNSCERT_H_ +#define DNSCERT_H_ + +typedef struct dnscert_t dnscert_t; +typedef enum dnscert_algorithm_t dnscert_algorithm_t; +typedef enum dnscert_type_t dnscert_type_t; + +#include + +/** + * DNS CERT types as defined in RFC 4398. + */ +enum dnscert_type_t { + /** Reserved value */ + DNSCERT_TYPE_RESERVED = 0, + /** An x509 PKIX certificate */ + DNSCERT_TYPE_PKIX = 1, + /** A SKPI certificate */ + DNSCERT_TYPE_SKPI = 2, + /** A PGP certificate */ + DNSCERT_TYPE_PGP = 3, + /** An x509 PKIX cert URL */ + DNSCERT_TYPE_IPKIX = 4, + /** A SKPI cert URL */ + DNSCERT_TYPE_ISKPI = 5, + /** A PGP cert fingerprint and URL */ + DNSCERT_TYPE_IPGP = 6, + /** An attribute Certificate */ + DNSCERT_TYPE_ACPKIX = 7, + /** An attribute cert URL */ + DNSCERT_TYPE_IACKPIX = 8 +}; + +/** + * DNSCERT algorithms as defined in http://www.iana.org/assignments/ + * dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml#dns-sec-alg-numbers-1 + */ +enum dnscert_algorithm_t { + /** No defined */ + DNSCERT_ALGORITHM_UNDEFINED = 0, + /** RSA/MD5 */ + DNSCERT_ALGORITHM_RSAMD5 = 1, + /** Diffie-Hellman */ + DNSCERT_ALGORITHM_DH = 2, + /** DSA/SHA1 */ + DNSCERT_ALGORITHM_DSASHA = 3, + /** Reserved */ + DNSCERT_ALGORITHM_RSRVD4 = 4, + /** RSA/SHA1 */ + DNSCERT_ALGORITHM_RSASHA = 5, + /** DSA/NSEC3/SHA */ + DNSCERT_ALGORITHM_DSANSEC3 = 6, + /** RSA/NSEC3/SHA */ + DNSCERT_ALGORITHM_RSANSEC3 = 7, + /** RSA/SHA256 */ + DNSCERT_ALGORITHM_RSASHA256 = 8, + /** Reserved */ + DNSCERT_ALGORITHM_RSRVD9 = 9, + /** RSA/SHA512 */ + DNSCERT_ALGORITHM_RSASHA512 = 10, +}; + +/** + * DNS CERT RR as defined in RFC 4398. + * + * The CERT resource record (RR) has the structure given below. Its RR + * type code is 37. + * + * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | type | key tag | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | algorithm | / + * +---------------+ certificate or CRL / + * / / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| + */ +struct dnscert_t { + + /** + * Get the type of the certificate body. + * + * The certificate "type" determines the format of the body + * of the CERT data. + * + * @return certificate type + */ + dnscert_type_t (*get_cert_type)(dnscert_t *this); + + /** + * Get the tag of the key part of the CERT. + * + * @return keytag + */ + u_int16_t (*get_key_tag)(dnscert_t *this); + + /** + * Get the algorithm. + * + * The "algorithm" determines the format of the public key field + * of the DNS CERT. + * + * @return algorithm + */ + dnscert_algorithm_t (*get_algorithm)(dnscert_t *this); + + /** + * Get the content of the certificate field as chunk. + * + * The format of the certificate depends on the type. + * + * The data pointed by the chunk is still owned by the DNSCERT. + * Clone it if necessary. + * + * @return certificate field as chunk + */ + chunk_t (*get_certificate)(dnscert_t *this); + + /** + * Destroy the DNSCERT. + */ + void (*destroy) (dnscert_t *this); +}; + +/** + * Create a dnscert instance out of a resource record. + * + * @param rr resource record which contains a DNSCERT + * @return dnscert, NULL on failure + */ +dnscert_t *dnscert_create_frm_rr(rr_t *rr); + +#endif /** DNSCERT_H_ @}*/ diff --git a/src/libcharon/plugins/dnscert/dnscert_cred.c b/src/libcharon/plugins/dnscert/dnscert_cred.c new file mode 100644 index 000000000..790252682 --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert_cred.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Reto Guadagnini + * 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. + */ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#define _GNU_SOURCE +#include +#include + +#include "dnscert_cred.h" +#include "dnscert.h" + +typedef struct private_dnscert_cred_t private_dnscert_cred_t; + +/** + * Private data of an dnscert_cred_t object + */ +struct private_dnscert_cred_t { + + /** + * Public part + */ + dnscert_cred_t public; + + /** + * DNS resolver + */ + resolver_t *res; +}; + +/** + * enumerator over certificates + */ +typedef struct { + /** implements enumerator interface */ + enumerator_t public; + /** inner enumerator (enumerates CERT resource records) */ + enumerator_t *inner; + /** response of the DNS resolver which contains the CERTs */ + resolver_response_t *response; +} cert_enumerator_t; + +METHOD(enumerator_t, cert_enumerator_enumerate, bool, + cert_enumerator_t *this, certificate_t **cert) +{ + dnscert_t *cur_crt; + rr_t *cur_rr; + chunk_t certificate; + + /* Get the next supported CERT using the inner enumerator. */ + while (this->inner->enumerate(this->inner, &cur_rr)) + { + cur_crt = dnscert_create_frm_rr(cur_rr); + + if (!cur_crt) + { + DBG1(DBG_CFG, " failed to parse CERT RR, skipping"); + continue; + } + + if (cur_crt->get_cert_type(cur_crt) != DNSCERT_TYPE_PKIX && + cur_crt->get_cert_type(cur_crt) != DNSCERT_TYPE_PGP) + { + DBG1(DBG_CFG, " unsupported CERT type [%d], skipping", + cur_crt->get_cert_type(cur_crt)); + cur_crt->destroy(cur_crt); + continue; + } + /* Try to parse PEM certificate container. Both x509 and PGP should + * presumably come as PEM encoded certs. */ + certificate = cur_crt->get_certificate(cur_crt); + *cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_ANY, + BUILD_BLOB_PEM, certificate, + BUILD_END); + if (*cert == NULL) + { + DBG1(DBG_CFG, " unable to parse certificate, skipping", + cur_crt->get_cert_type(cur_crt)); + cur_crt->destroy(cur_crt); + continue; + } + cur_crt->destroy(cur_crt); + return TRUE; + } + return FALSE; +} + +METHOD(enumerator_t, cert_enumerator_destroy, void, + cert_enumerator_t *this) +{ + this->inner->destroy(this->inner); + this->response->destroy(this->response); + free(this); +} + +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_dnscert_cred_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + resolver_response_t *response; + cert_enumerator_t *e; + char *fqdn; + + if (!id || id->get_type(id) != ID_FQDN) + { + return enumerator_create_empty(); + } + + /* query the DNS for the required CERT RRs */ + if (asprintf(&fqdn, "%Y", id) <= 0) + { + DBG1(DBG_CFG, "failed to determine FQDN to retrieve CERT RRs"); + return enumerator_create_empty(); + } + + DBG1(DBG_CFG, "performing a DNS query for CERT RRs of '%s'", fqdn); + response = this->res->query(this->res, fqdn, RR_CLASS_IN, RR_TYPE_CERT); + if (!response) + { + DBG1(DBG_CFG, " query for CERT RRs failed"); + free(fqdn); + return enumerator_create_empty(); + } + free(fqdn); + + if (!response->has_data(response) || + !response->query_name_exist(response)) + { + DBG1(DBG_CFG, " unable to retrieve CERT RRs from the DNS"); + response->destroy(response); + return enumerator_create_empty(); + } + + if (response->get_security_state(response) != SECURE) + { + DBG1(DBG_CFG, " DNSSEC state of CERT RRs is not secure"); + response->destroy(response); + return enumerator_create_empty(); + } + + INIT(e, + .public = { + .enumerate = (void*)_cert_enumerator_enumerate, + .destroy = _cert_enumerator_destroy, + }, + .inner = response->get_rr_set(response)->create_rr_enumerator( + response->get_rr_set(response)), + .response = response + ); + return &e->public; +} + +METHOD(dnscert_cred_t, destroy, void, + private_dnscert_cred_t *this) +{ + this->res->destroy(this->res); + free(this); +} + +/** + * Described in header. + */ +dnscert_cred_t *dnscert_cred_create(resolver_t *res) +{ + private_dnscert_cred_t *this; + + INIT(this, + .public = { + .set = { + .create_private_enumerator = (void*)return_null, + .create_cert_enumerator = _create_cert_enumerator, + .create_shared_enumerator = (void*)return_null, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)nop, + }, + .destroy = _destroy, + }, + .res = res, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/dnscert/dnscert_cred.h b/src/libcharon/plugins/dnscert/dnscert_cred.h new file mode 100644 index 000000000..ceaa68f09 --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert_cred.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup dnscert_cred_i dnscert_cred + * @{ @ingroup dnscert + */ + +#ifndef DNSCERT_CRED_H_ +#define DNSCERT_CRED_H_ + +#include +#include + +typedef struct dnscert_cred_t dnscert_cred_t; + +/** + * DNSCERT credential set. + * + * The dnscert credential set contains CERT RRs as certificates. + */ +struct dnscert_cred_t { + + /** + * Implements credential_set_t interface + */ + credential_set_t set; + + /** + * Destroy the dnscert_cred. + */ + void (*destroy)(dnscert_cred_t *this); +}; + +/** + * Create a dnscert_cred instance which uses the given resolver + * to query the DNS for CERT resource records. + * + * @param res resolver to use (gets adopted) + * @return credential set + */ +dnscert_cred_t *dnscert_cred_create(resolver_t *res); + +#endif /** DNSCERT_CRED_H_ @}*/ diff --git a/src/libcharon/plugins/dnscert/dnscert_plugin.c b/src/libcharon/plugins/dnscert/dnscert_plugin.c new file mode 100644 index 000000000..713bc9e3b --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert_plugin.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Reto Guadagnini + * 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. + */ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +#include "dnscert_plugin.h" + +#include +#include "dnscert_cred.h" + +typedef struct private_dnscert_plugin_t private_dnscert_plugin_t; + + +/** + * private data of the dnscert plugin + */ +struct private_dnscert_plugin_t { + + /** + * implements plugin interface + */ + dnscert_plugin_t public; + + /** + * credential set + */ + dnscert_cred_t *cred; + + /** + * DNSCERT based authentication enabled + */ + bool enabled; +}; + +METHOD(plugin_t, get_name, char*, + private_dnscert_plugin_t *this) +{ + return "dnscert"; +} + +METHOD(plugin_t, reload, bool, + private_dnscert_plugin_t *this) +{ + bool enabled = lib->settings->get_bool(lib->settings, + "%s.plugins.dnscert.enable", FALSE, charon->name); + + if (enabled != this->enabled) + { + if (enabled) + { + lib->credmgr->add_set(lib->credmgr, &this->cred->set); + } + else + { + lib->credmgr->remove_set(lib->credmgr, &this->cred->set); + } + this->enabled = enabled; + } + DBG1(DBG_CFG, "dnscert plugin is %sabled", this->enabled ? "en" : "dis"); + return TRUE; +} + +/** + * Create resolver and register credential set + */ +static bool plugin_cb(private_dnscert_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + resolver_t *res; + + res = lib->resolver->create(lib->resolver); + if (!res) + { + DBG1(DBG_CFG, "failed to create a DNS resolver instance"); + return FALSE; + } + + this->cred = dnscert_cred_create(res); + reload(this); + } + else + { + if (this->enabled) + { + lib->credmgr->remove_set(lib->credmgr, &this->cred->set); + } + this->cred->destroy(this->cred); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_dnscert_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "dnscert"), + PLUGIN_DEPENDS(RESOLVER), + PLUGIN_DEPENDS(CERT_DECODE, CERT_ANY), + PLUGIN_SDEPEND(CERT_DECODE, CERT_X509), + PLUGIN_SDEPEND(CERT_DECODE, CERT_GPG), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_dnscert_plugin_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *dnscert_plugin_create() +{ + private_dnscert_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .reload = _reload, + .destroy = _destroy, + }, + }, + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/dnscert/dnscert_plugin.h b/src/libcharon/plugins/dnscert/dnscert_plugin.h new file mode 100644 index 000000000..79ea64e40 --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert_plugin.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup dnscert dnscert + * @ingroup cplugins + * + * @defgroup dnscert_plugin dnscert_plugin + * @{ @ingroup dnscert + */ + +#ifndef DNSCERT_PLUGIN_H_ +#define DNSCERT_PLUGIN_H_ + +#include + +typedef struct dnscert_plugin_t dnscert_plugin_t; + +/** + * DNSCERT plugin + * + * The DNSCERT plugin registers a credential set for CERT RRs. + * + * With this credential set it is possible to authenticate tunnel endpoints + * using CERT resource records which are retrieved from the DNS in a secure + * way (DNSSEC). + */ +struct dnscert_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** DNSCERT_PLUGIN_H_ @}*/ From 42525d1142d3755e3f3123579f5fac5c15f8788e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 26 Sep 2013 17:00:21 +0200 Subject: [PATCH 6/9] testing: Load testing.conf.local from the same directory as testing.conf --- testing/testing.conf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/testing/testing.conf b/testing/testing.conf index 4b30ee04b..1e691f8cd 100644 --- a/testing/testing.conf +++ b/testing/testing.conf @@ -14,9 +14,10 @@ # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. -if [ -f testing.conf.local ] +TESTINGDIR=$(dirname `readlink -f ${BASH_SOURCE[0]}`) +if [ -f $TESTINGDIR/testing.conf.local ] then - . testing.conf.local + . $TESTINGDIR/testing.conf.local fi # Root directory of testing From 99a89ea7f4e84e1206a0aa1dce807219a6b1eed6 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 26 Sep 2013 17:01:11 +0200 Subject: [PATCH 7/9] testing: Enable dnscert plugin --- testing/scripts/recipes/013_strongswan.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/testing/scripts/recipes/013_strongswan.mk b/testing/scripts/recipes/013_strongswan.mk index efa4a77e3..85f80fe5b 100644 --- a/testing/scripts/recipes/013_strongswan.mk +++ b/testing/scripts/recipes/013_strongswan.mk @@ -75,6 +75,7 @@ CONFIG_OPTS = \ --enable-unity \ --enable-unbound \ --enable-ipseckey \ + --enable-dnscert \ --enable-cmd \ --enable-libipsec \ --enable-kernel-libipsec \ From a4d6a5a3595c1fc81a064a3736e4f9a24885de68 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 26 Sep 2013 18:16:10 +0200 Subject: [PATCH 8/9] testing: Provide moon's and sun's certificate as CERT RR --- .../hosts/winnetou/etc/bind/db.strongswan.org | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/testing/hosts/winnetou/etc/bind/db.strongswan.org b/testing/hosts/winnetou/etc/bind/db.strongswan.org index dfd2705cb..694e2cee1 100644 --- a/testing/hosts/winnetou/etc/bind/db.strongswan.org +++ b/testing/hosts/winnetou/etc/bind/db.strongswan.org @@ -31,6 +31,57 @@ crl IN CNAME winnetou.strongswan.org. ldap IN CNAME winnetou.strongswan.org. ocsp IN CNAME winnetou.strongswan.org. ; +moon IN CERT ( 1 0 0 + MIIEIjCCAwqgAwIBAgIBFzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ + MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS + b290IENBMB4XDTA5MDgyNzEwMDMzMloXDTE0MDgyNjEwMDMzMlowRjELMAkGA1UE + BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xHDAaBgNVBAMTE21vb24u + c3Ryb25nc3dhbi5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDK + L2M91Lu6BYYhWxWgMS9z9TMSTwszm5rhO7ZIsCtMRo4PAeYw+++SGXt3CPXb/+p+ + SWKGlm11rPE71eQ3ehgh2C3hAurfmWO0iQQaCw+fdreeIVCqOQIOP6UqZ327h5yY + YpHk8VQv4vBJTpxclU1PqnWheqe1ZlLxsW773LRml/fQt/UgvJkCBTZZONLNMfK+ + 7TDnYaVsAtncgvDN78nUNEe2qY92KK7SrBJ6SpUEg49m51F+XgsGcsgWVHS85on3 + Om/G48crLEVJjdu8CxewSRVgb+lPJWzHd8QsU0Vg/7vlqs3ZRMyNtNKrr4opSvVb + A6agGlTXhDCreDiXU8KHAgMBAAGjggEaMIIBFjAJBgNVHRMEAjAAMAsGA1UdDwQE + AwIDqDAdBgNVHQ4EFgQUapx00fiJeYn2WpTpifH6w2SdKS4wbQYDVR0jBGYwZIAU + XafdcAZRMn7ntm2zteXgYOouTe+hSaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQK + ExBMaW51eCBzdHJvbmdTd2FuMRswGQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GC + AQAwHgYDVR0RBBcwFYITbW9vbi5zdHJvbmdzd2FuLm9yZzATBgNVHSUEDDAKBggr + BgEFBQcDATA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vY3JsLnN0cm9uZ3N3YW4u + b3JnL3N0cm9uZ3N3YW4uY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQCctXg2xeMozaTV + jiBL1P8MY9uEH5JtU0EceQ1RbI5/2vGRdnECND9oADY5vamaaE2Mdq2Qh/vlXnML + o3ii5ELjsQlYdTYZOcMOdcUUXYvbbFX1cwpkBhyBl1H25KptHcgQ/HnceKp3kOuq + wYOYjgwePXulcpWXx0E2QtQCFQQZFPyEWeNJxH0oglg53QPXfHY9I2/Gukj5V0bz + p7ME0Gs8KdnYdmbbDqzQgPsta96/m+HoJlsrVF+4Gqihj6BWMBQ2ybjPWZdG3oH9 + 25cE8v60Ry98D0Z/tygbAUFnh5oOvaf642paVgc3aoA77I8U+UZjECxISoiHultY + 7QTufOwP + ) +sun IN CERT ( 1 0 0 + MIIEIDCCAwigAwIBAgIBFjANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ + MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS + b290IENBMB4XDTA5MDgyNzA5NTkwNFoXDTE0MDgyNjA5NTkwNFowRTELMAkGA1UE + BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN1bi5z + dHJvbmdzd2FuLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+V + VIpn6Q5jaU//EN6p6A5cSfUfhBK0mFa2laFFZh/Y0h66AXqqrQ3X917h7YNsSk68 + oowY9h9I3gOx7hNVBsJr2VjdYC+b0q5NTha09/A5mimv/prYj6o0yawxoPjoDs9Y + h7D7Kf+F8fkgk0stlHJZX66J7dNrFXbg1xBld+Ep5Or2FbEZ9QWUpRQTuhdpNt/4 + 9YuxQ59DemY9IRbwsrKCHH0mGrJsDdqeb0ap+8QvSXHjCt1fr9MNKWaAFAQLKQI4 + e0da1ntPCEQLeE833+NNRBgGufk0KqGT3eAXqrxa9AEIUJnVcPexQdqUMjcUpXFb + 8WNzRWB8Egh3BDK6FsECAwEAAaOCARkwggEVMAkGA1UdEwQCMAAwCwYDVR0PBAQD + AgOoMB0GA1UdDgQWBBRW1p4v2qihzRlcI1PnxbZwluML+zBtBgNVHSMEZjBkgBRd + p91wBlEyfue2bbO15eBg6i5N76FJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoT + EExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIB + ADAdBgNVHREEFjAUghJzdW4uc3Ryb25nc3dhbi5vcmcwEwYDVR0lBAwwCgYIKwYB + BQUHAwEwOQYDVR0fBDIwMDAuoCygKoYoaHR0cDovL2NybC5zdHJvbmdzd2FuLm9y + Zy9zdHJvbmdzd2FuLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAo37LYT9Awx0MK/nA + FZpPJqUr0Ey+O5Ukcsdx7nd00SlmpiQRY8KmuRXCBQnDEgdLstd3slQjT0pJEgWF + 0pzxybnI6eOzYAhLfhart+X1hURiNGbXjggm2s4I5+K32bVIkNEqlsYnd/6F9oo5 + ZNO0/eTTruLZfkNe/zchBGKe/Z7MacVwlYWWCbMtBV4K1d5dGcRRgpQ9WivDlmat + Nh9wlscDSgSGk3HJkbxnq695VN7zUbDWAUvWWhV5bIDjlAR/xyT9ApqIxiyVVRul + fYrE7U05Hbt6GgAroAKLp6qJup9+TxQAKSjKIwJ0hf7OuYyQ8TZtVHS7AOhm+T/5 + G/jGGA== + ) +; moon IN IPSECKEY ( 10 1 2 192.168.0.1 AwEAAcovYz3Uu7oFhiFbFaAxL3P1MxJPCzObmuE7tkiwK0xGjg8B5jD7 75IZe3cI9dv/6n5JYoaWbXWs8TvV5Dd6GCHYLeEC6t+ZY7SJBBoLD592 From ca28e13fe8692cd1243043cbfa75d28c78505e1a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Thu, 26 Sep 2013 18:28:48 +0200 Subject: [PATCH 9/9] testing: Add ikev2/net2net-dnscert scenario --- .../ikev2/net2net-dnscert/description.txt | 8 ++++++ .../tests/ikev2/net2net-dnscert/evaltest.dat | 9 ++++++ .../net2net-dnscert/hosts/moon/etc/ipsec.conf | 26 +++++++++++++++++ .../hosts/moon/etc/ipsec.d/dnssec.keys | 10 +++++++ .../hosts/moon/etc/iptables.rules | 28 +++++++++++++++++++ .../hosts/moon/etc/resolv.conf | 1 + .../hosts/moon/etc/strongswan.conf | 20 +++++++++++++ .../net2net-dnscert/hosts/sun/etc/ipsec.conf | 26 +++++++++++++++++ .../hosts/sun/etc/ipsec.d/dnssec.keys | 10 +++++++ .../hosts/sun/etc/iptables.rules | 28 +++++++++++++++++++ .../net2net-dnscert/hosts/sun/etc/resolv.conf | 1 + .../hosts/sun/etc/strongswan.conf | 20 +++++++++++++ .../tests/ikev2/net2net-dnscert/posttest.dat | 8 ++++++ .../tests/ikev2/net2net-dnscert/pretest.dat | 8 ++++++ testing/tests/ikev2/net2net-dnscert/test.conf | 21 ++++++++++++++ 15 files changed, 224 insertions(+) create mode 100644 testing/tests/ikev2/net2net-dnscert/description.txt create mode 100644 testing/tests/ikev2/net2net-dnscert/evaltest.dat create mode 100644 testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/ipsec.conf create mode 100644 testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/ipsec.d/dnssec.keys create mode 100644 testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/iptables.rules create mode 100644 testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/resolv.conf create mode 100644 testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/strongswan.conf create mode 100644 testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/ipsec.conf create mode 100644 testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/ipsec.d/dnssec.keys create mode 100644 testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/iptables.rules create mode 100644 testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/resolv.conf create mode 100644 testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/strongswan.conf create mode 100644 testing/tests/ikev2/net2net-dnscert/posttest.dat create mode 100644 testing/tests/ikev2/net2net-dnscert/pretest.dat create mode 100644 testing/tests/ikev2/net2net-dnscert/test.conf diff --git a/testing/tests/ikev2/net2net-dnscert/description.txt b/testing/tests/ikev2/net2net-dnscert/description.txt new file mode 100644 index 000000000..40c112bc4 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/description.txt @@ -0,0 +1,8 @@ +A connection between the subnets behind the gateways moon and sun is set up. +The authentication is based on trustworthy public keys stored as CERT +resource records in the Domain Name System (DNS) and protected by DNSSEC. +

+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, client alice behind gateway moon +pings client bob located behind gateway sun. diff --git a/testing/tests/ikev2/net2net-dnscert/evaltest.dat b/testing/tests/ikev2/net2net-dnscert/evaltest.dat new file mode 100644 index 000000000..effc9bc1f --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/evaltest.dat @@ -0,0 +1,9 @@ +moon:: cat /var/log/daemon.log::performing a DNS query for CERT RRs of.*sun.strongswan.org::YES +sun:: cat /var/log/daemon.log::performing a DNS query for CERT RRs of.*moon.strongswan.org::YES +moon:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES +sun:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES +moon:: ipsec status 2> /dev/null::INSTALLED, TUNNEL::YES +sun:: ipsec status 2> /dev/null::INSTALLED, TUNNEL::YES +alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES +sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES +sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES diff --git a/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/ipsec.conf new file mode 100644 index 000000000..3eaf60a1d --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/ipsec.conf @@ -0,0 +1,26 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev2 + mobike=no + +conn net-net + left=PH_IP_MOON + leftid=moon.strongswan.org + leftsubnet=10.1.0.0/16 + leftcert=moonCert.pem + leftsendcert=never + leftauth=pubkey + leftfirewall=yes + right=sun.strongswan.org + rightid=sun.strongswan.org + rightsubnet=10.2.0.0/16 + rightsendcert=never + rightauth=pubkey + auto=add diff --git a/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/ipsec.d/dnssec.keys b/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/ipsec.d/dnssec.keys new file mode 100644 index 000000000..d059d8476 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/ipsec.d/dnssec.keys @@ -0,0 +1,10 @@ +; This is a key-signing key, keyid 32329, for . +. IN DNSKEY 257 3 8 ( + AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2 + XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b + L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx + E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b + AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5 + nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO + O9fOgGnjzAk= + ) diff --git a/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/iptables.rules b/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/iptables.rules new file mode 100644 index 000000000..b2c425289 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/iptables.rules @@ -0,0 +1,28 @@ +*filter + +# default policy is DROP +-P INPUT DROP +-P OUTPUT DROP +-P FORWARD DROP + +# allow esp +-A INPUT -i eth0 -p 50 -j ACCEPT +-A OUTPUT -o eth0 -p 50 -j ACCEPT + +# allow IKE +-A INPUT -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT + +# allow MobIKE +-A INPUT -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT + +# allow ssh +-A INPUT -p tcp --dport 22 -j ACCEPT +-A OUTPUT -p tcp --sport 22 -j ACCEPT + +# allow DNSSEC fetch from winnetou +-A INPUT -i eth0 -p udp --sport 53 -s PH_IP_WINNETOU -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 53 -d PH_IP_WINNETOU -j ACCEPT + +COMMIT diff --git a/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/resolv.conf b/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/resolv.conf new file mode 100644 index 000000000..73d926def --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/resolv.conf @@ -0,0 +1 @@ +nameserver PH_IP_WINNETOU diff --git a/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/strongswan.conf new file mode 100644 index 000000000..e9c79b333 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/hosts/moon/etc/strongswan.conf @@ -0,0 +1,20 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = sha1 sha2 md5 aes des hmac gmp dnskey pem pkcs1 pubkey unbound dnscert random nonce x509 curl kernel-netlink socket-default stroke updown + + plugins { + dnscert { + enable = yes + } + } +} + +libstrongswan { + plugins { + unbound { + # trust_anchors = /etc/ipsec.d/dnssec.keys + # resolv_conf = /etc/resolv.conf + } + } +} diff --git a/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/ipsec.conf b/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/ipsec.conf new file mode 100644 index 000000000..75c4addda --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/ipsec.conf @@ -0,0 +1,26 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev2 + mobike=no + +conn net-net + left=PH_IP_SUN + leftid=sun.strongswan.org + leftsubnet=10.2.0.0/16 + leftcert=sunCert.pem + leftsendcert=never + leftauth=pubkey + leftfirewall=yes + right=moon.strongswan.org + rightid=moon.strongswan.org + rightsubnet=10.1.0.0/16 + rightsendcert=never + rightauth=pubkey + auto=add diff --git a/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/ipsec.d/dnssec.keys b/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/ipsec.d/dnssec.keys new file mode 100644 index 000000000..d059d8476 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/ipsec.d/dnssec.keys @@ -0,0 +1,10 @@ +; This is a key-signing key, keyid 32329, for . +. IN DNSKEY 257 3 8 ( + AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2 + XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b + L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx + E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b + AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5 + nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO + O9fOgGnjzAk= + ) diff --git a/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/iptables.rules b/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/iptables.rules new file mode 100644 index 000000000..b2c425289 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/iptables.rules @@ -0,0 +1,28 @@ +*filter + +# default policy is DROP +-P INPUT DROP +-P OUTPUT DROP +-P FORWARD DROP + +# allow esp +-A INPUT -i eth0 -p 50 -j ACCEPT +-A OUTPUT -o eth0 -p 50 -j ACCEPT + +# allow IKE +-A INPUT -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT + +# allow MobIKE +-A INPUT -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT + +# allow ssh +-A INPUT -p tcp --dport 22 -j ACCEPT +-A OUTPUT -p tcp --sport 22 -j ACCEPT + +# allow DNSSEC fetch from winnetou +-A INPUT -i eth0 -p udp --sport 53 -s PH_IP_WINNETOU -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 53 -d PH_IP_WINNETOU -j ACCEPT + +COMMIT diff --git a/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/resolv.conf b/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/resolv.conf new file mode 100644 index 000000000..73d926def --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/resolv.conf @@ -0,0 +1 @@ +nameserver PH_IP_WINNETOU diff --git a/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/strongswan.conf b/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/strongswan.conf new file mode 100644 index 000000000..e9c79b333 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/hosts/sun/etc/strongswan.conf @@ -0,0 +1,20 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = sha1 sha2 md5 aes des hmac gmp dnskey pem pkcs1 pubkey unbound dnscert random nonce x509 curl kernel-netlink socket-default stroke updown + + plugins { + dnscert { + enable = yes + } + } +} + +libstrongswan { + plugins { + unbound { + # trust_anchors = /etc/ipsec.d/dnssec.keys + # resolv_conf = /etc/resolv.conf + } + } +} diff --git a/testing/tests/ikev2/net2net-dnscert/posttest.dat b/testing/tests/ikev2/net2net-dnscert/posttest.dat new file mode 100644 index 000000000..c594c4dc8 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/posttest.dat @@ -0,0 +1,8 @@ +moon::ipsec stop +sun::ipsec stop +moon::iptables-restore < /etc/iptables.flush +sun::iptables-restore < /etc/iptables.flush +moon::rm /etc/resolv.conf +sun::rm /etc/resolv.conf +moon::rm /etc/ipsec.d/dnssec.keys +sun::rm /etc/ipsec.d/dnssec.keys diff --git a/testing/tests/ikev2/net2net-dnscert/pretest.dat b/testing/tests/ikev2/net2net-dnscert/pretest.dat new file mode 100644 index 000000000..0f4ae0f4f --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/pretest.dat @@ -0,0 +1,8 @@ +moon::iptables-restore < /etc/iptables.rules +sun::iptables-restore < /etc/iptables.rules +moon::rm /etc/ipsec.d/cacerts/* +sun::rm /etc/ipsec.d/cacerts/* +moon::ipsec start +sun::ipsec start +moon::sleep 2 +moon::ipsec up net-net diff --git a/testing/tests/ikev2/net2net-dnscert/test.conf b/testing/tests/ikev2/net2net-dnscert/test.conf new file mode 100644 index 000000000..afa2accbe --- /dev/null +++ b/testing/tests/ikev2/net2net-dnscert/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 winnetou sun bob" + +# Corresponding block diagram +# +DIAGRAM="a-m-w-s-b.png" + +# Guest instances on which tcpdump is to be started +# +TCPDUMPHOSTS="sun" + +# Guest instances on which IPsec is started +# Used for IPsec logging purposes +# +IPSECHOSTS="moon sun"