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:
@@ -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([pgp], [disable PGP key decoding plugin.])
|
||||||
ARG_DISBL_SET([dnskey], [disable DNS RR key decoding plugin.])
|
ARG_DISBL_SET([dnskey], [disable DNS RR key decoding plugin.])
|
||||||
ARG_DISBL_SET([sshkey], [disable SSH 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_ENABL_SET([ipseckey], [enable IPSECKEY authentication plugin.])
|
||||||
ARG_DISBL_SET([pem], [disable PEM decoding plugin.])
|
ARG_DISBL_SET([pem], [disable PEM decoding plugin.])
|
||||||
ARG_DISBL_SET([hmac], [disable HMAC crypto implementation 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([pgp], [s charon])
|
||||||
ADD_PLUGIN([dnskey], [s charon pki])
|
ADD_PLUGIN([dnskey], [s charon pki])
|
||||||
ADD_PLUGIN([sshkey], [s charon pki nm cmd])
|
ADD_PLUGIN([sshkey], [s charon pki nm cmd])
|
||||||
|
ADD_PLUGIN([dnscert], [c charon])
|
||||||
ADD_PLUGIN([ipseckey], [c charon])
|
ADD_PLUGIN([ipseckey], [c charon])
|
||||||
ADD_PLUGIN([pem], [s charon openac scepclient pki scripts manager medsrv attest nm cmd])
|
ADD_PLUGIN([pem], [s charon openac scepclient pki scripts manager medsrv attest nm cmd])
|
||||||
ADD_PLUGIN([padlock], [s charon])
|
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_MAEMO, test x$maemo = xtrue)
|
||||||
AM_CONDITIONAL(USE_SMP, test x$smp = xtrue)
|
AM_CONDITIONAL(USE_SMP, test x$smp = xtrue)
|
||||||
AM_CONDITIONAL(USE_SQL, test x$sql = 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_IPSECKEY, test x$ipseckey = xtrue)
|
||||||
AM_CONDITIONAL(USE_UPDOWN, test x$updown = xtrue)
|
AM_CONDITIONAL(USE_UPDOWN, test x$updown = xtrue)
|
||||||
AM_CONDITIONAL(USE_DHCP, test x$dhcp = xtrue)
|
AM_CONDITIONAL(USE_DHCP, test x$dhcp = xtrue)
|
||||||
@@ -1442,6 +1445,7 @@ AC_CONFIG_FILES([
|
|||||||
src/libcharon/plugins/farp/Makefile
|
src/libcharon/plugins/farp/Makefile
|
||||||
src/libcharon/plugins/smp/Makefile
|
src/libcharon/plugins/smp/Makefile
|
||||||
src/libcharon/plugins/sql/Makefile
|
src/libcharon/plugins/sql/Makefile
|
||||||
|
src/libcharon/plugins/dnscert/Makefile
|
||||||
src/libcharon/plugins/ipseckey/Makefile
|
src/libcharon/plugins/ipseckey/Makefile
|
||||||
src/libcharon/plugins/medsrv/Makefile
|
src/libcharon/plugins/medsrv/Makefile
|
||||||
src/libcharon/plugins/medcli/Makefile
|
src/libcharon/plugins/medcli/Makefile
|
||||||
|
|||||||
@@ -886,7 +886,15 @@ File to read pseudo random bytes from, instead of @urandom_device@
|
|||||||
File to read DNS resolver configuration from
|
File to read DNS resolver configuration from
|
||||||
.TP
|
.TP
|
||||||
.BR libstrongswan.plugins.unbound.trust_anchors " [/etc/ipsec.d/dnssec.keys]"
|
.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
|
.SS libtls section
|
||||||
.TP
|
.TP
|
||||||
.BR libtls.cipher
|
.BR libtls.cipher
|
||||||
|
|||||||
@@ -216,6 +216,13 @@ if MONOLITHIC
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if USE_DNSCERT
|
||||||
|
SUBDIRS += plugins/dnscert
|
||||||
|
if MONOLITHIC
|
||||||
|
libcharon_la_LIBADD += plugins/dnscert/libstrongswan-dnscert.la
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
if USE_IPSECKEY
|
if USE_IPSECKEY
|
||||||
SUBDIRS += plugins/ipseckey
|
SUBDIRS += plugins/ipseckey
|
||||||
if MONOLITHIC
|
if MONOLITHIC
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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_ @}*/
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (C) 2013 Tobias Brunner
|
||||||
* Copyright (C) 2012 Reto Guadagnini
|
* Copyright (C) 2012 Reto Guadagnini
|
||||||
* Hochschule fuer Technik Rapperswil
|
* Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
@@ -12,6 +13,7 @@
|
|||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
* for more details.
|
* for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -20,7 +22,6 @@
|
|||||||
#include "ipseckey.h"
|
#include "ipseckey.h"
|
||||||
|
|
||||||
#include <bio/bio_reader.h>
|
#include <bio/bio_reader.h>
|
||||||
#include <daemon.h>
|
|
||||||
|
|
||||||
typedef struct private_ipseckey_cred_t private_ipseckey_cred_t;
|
typedef struct private_ipseckey_cred_t private_ipseckey_cred_t;
|
||||||
|
|
||||||
@@ -61,64 +62,59 @@ typedef struct {
|
|||||||
METHOD(enumerator_t, cert_enumerator_enumerate, bool,
|
METHOD(enumerator_t, cert_enumerator_enumerate, bool,
|
||||||
cert_enumerator_t *this, certificate_t **cert)
|
cert_enumerator_t *this, certificate_t **cert)
|
||||||
{
|
{
|
||||||
rr_t *cur_rr = NULL;
|
ipseckey_t *cur_ipseckey;
|
||||||
ipseckey_t *cur_ipseckey = NULL;
|
public_key_t *public;
|
||||||
chunk_t pub_key;
|
rr_t *cur_rr;
|
||||||
public_key_t * key = NULL;
|
chunk_t key;
|
||||||
bool supported_ipseckey_found = FALSE;
|
|
||||||
|
|
||||||
/* Get the next supported IPSECKEY using the inner enumerator. */
|
/* Get the next supported IPSECKEY using the inner enumerator. */
|
||||||
while (this->inner->enumerate(this->inner, &cur_rr) &&
|
while (this->inner->enumerate(this->inner, &cur_rr))
|
||||||
!supported_ipseckey_found)
|
|
||||||
{
|
{
|
||||||
supported_ipseckey_found = TRUE;
|
|
||||||
|
|
||||||
cur_ipseckey = ipseckey_create_frm_rr(cur_rr);
|
cur_ipseckey = ipseckey_create_frm_rr(cur_rr);
|
||||||
|
|
||||||
if (!cur_ipseckey)
|
if (!cur_ipseckey)
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "failed to parse ipseckey - skipping this key");
|
DBG1(DBG_CFG, " failed to parse IPSECKEY, skipping");
|
||||||
supported_ipseckey_found = FALSE;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur_ipseckey &&
|
if (cur_ipseckey->get_algorithm(cur_ipseckey) != IPSECKEY_ALGORITHM_RSA)
|
||||||
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);
|
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 */
|
||||||
/*
|
key = cur_ipseckey->get_public_key(cur_ipseckey);
|
||||||
* Wrap the key of the IPSECKEY in a certificate and return this
|
public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
|
||||||
* certificate.
|
BUILD_BLOB_DNSKEY, key,
|
||||||
*/
|
BUILD_END);
|
||||||
pub_key = cur_ipseckey->get_public_key(cur_ipseckey);
|
if (!public)
|
||||||
|
|
||||||
key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
|
|
||||||
BUILD_BLOB_DNSKEY, pub_key,
|
|
||||||
BUILD_END);
|
|
||||||
|
|
||||||
if (!key)
|
|
||||||
{
|
{
|
||||||
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);
|
cur_ipseckey->destroy(cur_ipseckey);
|
||||||
return FALSE;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
|
*cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
|
||||||
CERT_TRUSTED_PUBKEY,
|
CERT_TRUSTED_PUBKEY,
|
||||||
BUILD_PUBLIC_KEY, key,
|
BUILD_PUBLIC_KEY, public,
|
||||||
BUILD_SUBJECT, this->identity,
|
BUILD_SUBJECT, this->identity,
|
||||||
BUILD_NOT_BEFORE_TIME, this->notBefore,
|
BUILD_NOT_BEFORE_TIME, this->notBefore,
|
||||||
BUILD_NOT_AFTER_TIME, this->notAfter,
|
BUILD_NOT_AFTER_TIME, this->notAfter,
|
||||||
BUILD_END);
|
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 TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FALSE;
|
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,
|
private_ipseckey_cred_t *this, certificate_type_t cert, key_type_t key,
|
||||||
identification_t *id, bool trusted)
|
identification_t *id, bool trusted)
|
||||||
{
|
{
|
||||||
char *fqdn = NULL;
|
resolver_response_t *response;
|
||||||
resolver_response_t *response = NULL;
|
enumerator_t *rrsig_enum;
|
||||||
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;
|
|
||||||
cert_enumerator_t *e;
|
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 */
|
return enumerator_create_empty();
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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,
|
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_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
|
||||||
PLUGIN_PROVIDE(CUSTOM, "ipseckey"),
|
PLUGIN_PROVIDE(CUSTOM, "ipseckey"),
|
||||||
PLUGIN_DEPENDS(RESOLVER),
|
PLUGIN_DEPENDS(RESOLVER),
|
||||||
|
PLUGIN_DEPENDS(PUBKEY, KEY_RSA),
|
||||||
|
PLUGIN_DEPENDS(CERT_ENCODE, CERT_TRUSTED_PUBKEY),
|
||||||
};
|
};
|
||||||
*features = f;
|
*features = f;
|
||||||
return countof(f);
|
return countof(f);
|
||||||
|
|||||||
@@ -94,16 +94,17 @@ resolver_t *unbound_resolver_create(void)
|
|||||||
{
|
{
|
||||||
private_resolver_t *this;
|
private_resolver_t *this;
|
||||||
int ub_retval = 0;
|
int ub_retval = 0;
|
||||||
char *resolv_conf_file;
|
char *resolv_conf, *trust_anchors, *dlv_anchors;
|
||||||
char *trust_anchor_file;
|
|
||||||
|
|
||||||
resolv_conf_file = lib->settings->get_str(lib->settings,
|
resolv_conf = lib->settings->get_str(lib->settings,
|
||||||
"libstrongswan.plugins.unbound.resolv_conf",
|
"libstrongswan.plugins.unbound.resolv_conf",
|
||||||
RESOLV_CONF_FILE);
|
RESOLV_CONF_FILE);
|
||||||
|
trust_anchors = lib->settings->get_str(lib->settings,
|
||||||
trust_anchor_file = lib->settings->get_str(lib->settings,
|
|
||||||
"libstrongswan.plugins.unbound.trust_anchors",
|
"libstrongswan.plugins.unbound.trust_anchors",
|
||||||
TRUST_ANCHOR_FILE);
|
TRUST_ANCHOR_FILE);
|
||||||
|
dlv_anchors = lib->settings->get_str(lib->settings,
|
||||||
|
"libstrongswan.plugins.unbound.dlv_anchors",
|
||||||
|
NULL);
|
||||||
|
|
||||||
INIT(this,
|
INIT(this,
|
||||||
.public = {
|
.public = {
|
||||||
@@ -120,24 +121,34 @@ resolver_t *unbound_resolver_create(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG1(DBG_CFG, "loading unbound resolver config from '%s'", resolv_conf_file);
|
DBG2(DBG_CFG, "loading unbound resolver config from '%s'", resolv_conf);
|
||||||
ub_retval = ub_ctx_resolvconf(this->ctx, resolv_conf_file);
|
ub_retval = ub_ctx_resolvconf(this->ctx, resolv_conf);
|
||||||
if (ub_retval)
|
if (ub_retval)
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "failed to read the resolver config: %s (%s)",
|
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);
|
destroy(this);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBG1(DBG_CFG, "loading unbound trust anchors from '%s'", trust_anchor_file);
|
DBG2(DBG_CFG, "loading unbound trust anchors from '%s'", trust_anchors);
|
||||||
ub_retval = ub_ctx_add_ta_file(this->ctx, trust_anchor_file);
|
ub_retval = ub_ctx_add_ta_file(this->ctx, trust_anchors);
|
||||||
if (ub_retval)
|
if (ub_retval)
|
||||||
{
|
{
|
||||||
DBG1(DBG_CFG, "failed to load trust anchors: %s (%s)",
|
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;
|
return &this->public;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,57 @@ crl IN CNAME winnetou.strongswan.org.
|
|||||||
ldap IN CNAME winnetou.strongswan.org.
|
ldap IN CNAME winnetou.strongswan.org.
|
||||||
ocsp 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
|
moon IN IPSECKEY ( 10 1 2 192.168.0.1
|
||||||
AwEAAcovYz3Uu7oFhiFbFaAxL3P1MxJPCzObmuE7tkiwK0xGjg8B5jD7
|
AwEAAcovYz3Uu7oFhiFbFaAxL3P1MxJPCzObmuE7tkiwK0xGjg8B5jD7
|
||||||
75IZe3cI9dv/6n5JYoaWbXWs8TvV5Dd6GCHYLeEC6t+ZY7SJBBoLD592
|
75IZe3cI9dv/6n5JYoaWbXWs8TvV5Dd6GCHYLeEC6t+ZY7SJBBoLD592
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ CONFIG_OPTS = \
|
|||||||
--enable-unity \
|
--enable-unity \
|
||||||
--enable-unbound \
|
--enable-unbound \
|
||||||
--enable-ipseckey \
|
--enable-ipseckey \
|
||||||
|
--enable-dnscert \
|
||||||
--enable-cmd \
|
--enable-cmd \
|
||||||
--enable-libipsec \
|
--enable-libipsec \
|
||||||
--enable-kernel-libipsec \
|
--enable-kernel-libipsec \
|
||||||
|
|||||||
@@ -14,9 +14,10 @@
|
|||||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
# for more details.
|
# for more details.
|
||||||
|
|
||||||
if [ -f testing.conf.local ]
|
TESTINGDIR=$(dirname `readlink -f ${BASH_SOURCE[0]}`)
|
||||||
|
if [ -f $TESTINGDIR/testing.conf.local ]
|
||||||
then
|
then
|
||||||
. testing.conf.local
|
. $TESTINGDIR/testing.conf.local
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Root directory of testing
|
# 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"
|
||||||
Reference in New Issue
Block a user