Merge branch 'dnscert'

The new dnscert plugin adds support for authentication via CERT resource
records that are protected with DNSSEC.
This commit is contained in:
Tobias Brunner
2013-10-11 15:49:24 +02:00
31 changed files with 1258 additions and 138 deletions
+4
View File
@@ -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
+9 -1
View File
@@ -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
+7
View File
@@ -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
+20
View File
@@ -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
+142
View File
@@ -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 <library.h>
#include <utils/debug.h>
#include <bio/bio_reader.h>
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;
}
+161
View File
@@ -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 <library.h>
/**
* 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_ @}*/
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/*
* Copyright (C) 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 <stdio.h>
#include <string.h>
#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;
}
@@ -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 <credentials/credential_set.h>
#include <resolver/resolver.h>
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_ @}*/
@@ -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 <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/*
* Copyright (C) 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 <daemon.h>
#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;
}
@@ -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 <plugins/plugin.h>
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_ @}*/
+113 -123
View File
@@ -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 <stdio.h>
#include <string.h>
@@ -20,7 +22,6 @@
#include "ipseckey.h"
#include <bio/bio_reader.h>
#include <daemon.h>
typedef struct private_ipseckey_cred_t private_ipseckey_cred_t;
@@ -61,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;
}
@@ -134,101 +130,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,
@@ -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);
@@ -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;
}
@@ -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
@@ -75,6 +75,7 @@ CONFIG_OPTS = \
--enable-unity \
--enable-unbound \
--enable-ipseckey \
--enable-dnscert \
--enable-cmd \
--enable-libipsec \
--enable-kernel-libipsec \
+3 -2
View File
@@ -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
@@ -0,0 +1,8 @@
A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up.
The authentication is based on trustworthy public keys stored as <b>CERT</b>
resource records in the Domain Name System (DNS) and protected by <b>DNSSEC</b>.
<p/>
Upon the successful establishment of the IPsec tunnel, <b>leftfirewall=yes</b>
automatically inserts iptables-based firewall rules that let pass the tunneled traffic.
In order to test both tunnel and firewall, client <b>alice</b> behind gateway <b>moon</b>
pings client <b>bob</b> located behind gateway <b>sun</b>.
@@ -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
@@ -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
@@ -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=
)
@@ -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
@@ -0,0 +1 @@
nameserver PH_IP_WINNETOU
@@ -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
}
}
}
@@ -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
@@ -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=
)
@@ -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
@@ -0,0 +1 @@
nameserver PH_IP_WINNETOU
@@ -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
}
}
}
@@ -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
@@ -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
@@ -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"