diff --git a/configure.ac b/configure.ac index 66cbfa987..82c530424 100644 --- a/configure.ac +++ b/configure.ac @@ -136,6 +136,7 @@ ARG_DISBL_SET([pkcs12], [disable PKCS12 container support plugin.]) ARG_DISBL_SET([pgp], [disable PGP key decoding plugin.]) ARG_DISBL_SET([dnskey], [disable DNS RR key decoding plugin.]) ARG_DISBL_SET([sshkey], [disable SSH key decoding plugin.]) +ARG_ENABL_SET([dnscert], [enable DNSCERT authentication plugin.]) ARG_ENABL_SET([ipseckey], [enable IPSECKEY authentication plugin.]) ARG_DISBL_SET([pem], [disable PEM decoding plugin.]) ARG_DISBL_SET([hmac], [disable HMAC crypto implementation plugin.]) @@ -1015,6 +1016,7 @@ ADD_PLUGIN([pkcs12], [s charon scepclient pki scripts cmd]) ADD_PLUGIN([pgp], [s charon]) ADD_PLUGIN([dnskey], [s charon pki]) ADD_PLUGIN([sshkey], [s charon pki nm cmd]) +ADD_PLUGIN([dnscert], [c charon]) ADD_PLUGIN([ipseckey], [c charon]) ADD_PLUGIN([pem], [s charon openac scepclient pki scripts manager medsrv attest nm cmd]) ADD_PLUGIN([padlock], [s charon]) @@ -1181,6 +1183,7 @@ AM_CONDITIONAL(USE_ANDROID_LOG, test x$android_log = xtrue) AM_CONDITIONAL(USE_MAEMO, test x$maemo = xtrue) AM_CONDITIONAL(USE_SMP, test x$smp = xtrue) AM_CONDITIONAL(USE_SQL, test x$sql = xtrue) +AM_CONDITIONAL(USE_DNSCERT, test x$dnscert = xtrue) AM_CONDITIONAL(USE_IPSECKEY, test x$ipseckey = xtrue) AM_CONDITIONAL(USE_UPDOWN, test x$updown = xtrue) AM_CONDITIONAL(USE_DHCP, test x$dhcp = xtrue) @@ -1442,6 +1445,7 @@ AC_CONFIG_FILES([ src/libcharon/plugins/farp/Makefile src/libcharon/plugins/smp/Makefile src/libcharon/plugins/sql/Makefile + src/libcharon/plugins/dnscert/Makefile src/libcharon/plugins/ipseckey/Makefile src/libcharon/plugins/medsrv/Makefile src/libcharon/plugins/medcli/Makefile diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 5ee047b9c..df58eaa10 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -216,6 +216,13 @@ if MONOLITHIC endif endif +if USE_DNSCERT + SUBDIRS += plugins/dnscert +if MONOLITHIC + libcharon_la_LIBADD += plugins/dnscert/libstrongswan-dnscert.la +endif +endif + if USE_IPSECKEY SUBDIRS += plugins/ipseckey if MONOLITHIC diff --git a/src/libcharon/plugins/dnscert/Makefile.am b/src/libcharon/plugins/dnscert/Makefile.am new file mode 100644 index 000000000..51d542b30 --- /dev/null +++ b/src/libcharon/plugins/dnscert/Makefile.am @@ -0,0 +1,20 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-dnscert.la +else +plugin_LTLIBRARIES = libstrongswan-dnscert.la +endif + +libstrongswan_dnscert_la_SOURCES = \ + dnscert_plugin.h dnscert_plugin.c \ + dnscert_cred.h dnscert_cred.c \ + dnscert.h dnscert.c + +libstrongswan_dnscert_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/dnscert/dnscert.c b/src/libcharon/plugins/dnscert/dnscert.c new file mode 100644 index 000000000..882ad9f0c --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "dnscert.h" + +#include +#include +#include + +typedef struct private_dnscert_t private_dnscert_t; + +/** +* private data of the dnscert +*/ +struct private_dnscert_t { + + /** + * public functions + */ + dnscert_t public; + + /** + * Certificate type + */ + u_int16_t cert_type; + + /** + * Key tag + */ + u_int16_t key_tag; + + /** + * Algorithm + */ + u_int8_t algorithm; + + /** + * Certificate + */ + chunk_t certificate; +}; + +METHOD(dnscert_t, get_cert_type, dnscert_type_t, + private_dnscert_t *this) +{ + return this->cert_type; +} + +METHOD(dnscert_t, get_key_tag, u_int16_t, + private_dnscert_t *this) +{ + return this->key_tag; +} + +METHOD(dnscert_t, get_algorithm, dnscert_algorithm_t, + private_dnscert_t *this) +{ + return this->algorithm; +} + +METHOD(dnscert_t, get_certificate, chunk_t, + private_dnscert_t *this) +{ + return this->certificate; +} + +METHOD(dnscert_t, destroy, void, + private_dnscert_t *this) +{ + chunk_free(&this->certificate); + free(this); +} + +dnscert_t *dnscert_create_frm_rr(rr_t *rr) +{ + private_dnscert_t *this; + bio_reader_t *reader = NULL; + + INIT(this, + .public = { + .get_cert_type = _get_cert_type, + .get_key_tag = _get_key_tag, + .get_algorithm = _get_algorithm, + .get_certificate = _get_certificate, + .destroy = _destroy, + }, + ); + + if (rr->get_type(rr) != RR_TYPE_CERT) + { + DBG1(DBG_CFG, "unable to create a dnscert out of an RR " + "whose type is not CERT"); + free(this); + return NULL; + } + + /** + * Parse the content (RDATA field) of the RR + * First - type/tag/algo fields and then cert body + */ + reader = bio_reader_create(rr->get_rdata(rr)); + if (!reader->read_uint16(reader, &this->cert_type) || + !reader->read_uint16(reader, &this->key_tag) || + !reader->read_uint8(reader, &this->algorithm) ) + { + DBG1(DBG_CFG, "CERT RR has a wrong format"); + reader->destroy(reader); + free(this); + return NULL; + } + + if (!reader->read_data(reader, reader->remaining(reader), + &this->certificate)) + { + DBG1(DBG_CFG, "failed to read DNS certificate field"); + reader->destroy(reader); + free(this); + return NULL; + } + this->certificate = chunk_clone(this->certificate); + reader->destroy(reader); + return &this->public; +} diff --git a/src/libcharon/plugins/dnscert/dnscert.h b/src/libcharon/plugins/dnscert/dnscert.h new file mode 100644 index 000000000..f93263fd6 --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert.h @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup dnscert_i dnscert + * @{ @ingroup dnscert + */ + +#ifndef DNSCERT_H_ +#define DNSCERT_H_ + +typedef struct dnscert_t dnscert_t; +typedef enum dnscert_algorithm_t dnscert_algorithm_t; +typedef enum dnscert_type_t dnscert_type_t; + +#include + +/** + * DNS CERT types as defined in RFC 4398. + */ +enum dnscert_type_t { + /** Reserved value */ + DNSCERT_TYPE_RESERVED = 0, + /** An x509 PKIX certificate */ + DNSCERT_TYPE_PKIX = 1, + /** A SKPI certificate */ + DNSCERT_TYPE_SKPI = 2, + /** A PGP certificate */ + DNSCERT_TYPE_PGP = 3, + /** An x509 PKIX cert URL */ + DNSCERT_TYPE_IPKIX = 4, + /** A SKPI cert URL */ + DNSCERT_TYPE_ISKPI = 5, + /** A PGP cert fingerprint and URL */ + DNSCERT_TYPE_IPGP = 6, + /** An attribute Certificate */ + DNSCERT_TYPE_ACPKIX = 7, + /** An attribute cert URL */ + DNSCERT_TYPE_IACKPIX = 8 +}; + +/** + * DNSCERT algorithms as defined in http://www.iana.org/assignments/ + * dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml#dns-sec-alg-numbers-1 + */ +enum dnscert_algorithm_t { + /** No defined */ + DNSCERT_ALGORITHM_UNDEFINED = 0, + /** RSA/MD5 */ + DNSCERT_ALGORITHM_RSAMD5 = 1, + /** Diffie-Hellman */ + DNSCERT_ALGORITHM_DH = 2, + /** DSA/SHA1 */ + DNSCERT_ALGORITHM_DSASHA = 3, + /** Reserved */ + DNSCERT_ALGORITHM_RSRVD4 = 4, + /** RSA/SHA1 */ + DNSCERT_ALGORITHM_RSASHA = 5, + /** DSA/NSEC3/SHA */ + DNSCERT_ALGORITHM_DSANSEC3 = 6, + /** RSA/NSEC3/SHA */ + DNSCERT_ALGORITHM_RSANSEC3 = 7, + /** RSA/SHA256 */ + DNSCERT_ALGORITHM_RSASHA256 = 8, + /** Reserved */ + DNSCERT_ALGORITHM_RSRVD9 = 9, + /** RSA/SHA512 */ + DNSCERT_ALGORITHM_RSASHA512 = 10, +}; + +/** + * DNS CERT RR as defined in RFC 4398. + * + * The CERT resource record (RR) has the structure given below. Its RR + * type code is 37. + * + * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | type | key tag | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | algorithm | / + * +---------------+ certificate or CRL / + * / / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| + */ +struct dnscert_t { + + /** + * Get the type of the certificate body. + * + * The certificate "type" determines the format of the body + * of the CERT data. + * + * @return certificate type + */ + dnscert_type_t (*get_cert_type)(dnscert_t *this); + + /** + * Get the tag of the key part of the CERT. + * + * @return keytag + */ + u_int16_t (*get_key_tag)(dnscert_t *this); + + /** + * Get the algorithm. + * + * The "algorithm" determines the format of the public key field + * of the DNS CERT. + * + * @return algorithm + */ + dnscert_algorithm_t (*get_algorithm)(dnscert_t *this); + + /** + * Get the content of the certificate field as chunk. + * + * The format of the certificate depends on the type. + * + * The data pointed by the chunk is still owned by the DNSCERT. + * Clone it if necessary. + * + * @return certificate field as chunk + */ + chunk_t (*get_certificate)(dnscert_t *this); + + /** + * Destroy the DNSCERT. + */ + void (*destroy) (dnscert_t *this); +}; + +/** + * Create a dnscert instance out of a resource record. + * + * @param rr resource record which contains a DNSCERT + * @return dnscert, NULL on failure + */ +dnscert_t *dnscert_create_frm_rr(rr_t *rr); + +#endif /** DNSCERT_H_ @}*/ diff --git a/src/libcharon/plugins/dnscert/dnscert_cred.c b/src/libcharon/plugins/dnscert/dnscert_cred.c new file mode 100644 index 000000000..790252682 --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert_cred.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Reto Guadagnini + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#define _GNU_SOURCE +#include +#include + +#include "dnscert_cred.h" +#include "dnscert.h" + +typedef struct private_dnscert_cred_t private_dnscert_cred_t; + +/** + * Private data of an dnscert_cred_t object + */ +struct private_dnscert_cred_t { + + /** + * Public part + */ + dnscert_cred_t public; + + /** + * DNS resolver + */ + resolver_t *res; +}; + +/** + * enumerator over certificates + */ +typedef struct { + /** implements enumerator interface */ + enumerator_t public; + /** inner enumerator (enumerates CERT resource records) */ + enumerator_t *inner; + /** response of the DNS resolver which contains the CERTs */ + resolver_response_t *response; +} cert_enumerator_t; + +METHOD(enumerator_t, cert_enumerator_enumerate, bool, + cert_enumerator_t *this, certificate_t **cert) +{ + dnscert_t *cur_crt; + rr_t *cur_rr; + chunk_t certificate; + + /* Get the next supported CERT using the inner enumerator. */ + while (this->inner->enumerate(this->inner, &cur_rr)) + { + cur_crt = dnscert_create_frm_rr(cur_rr); + + if (!cur_crt) + { + DBG1(DBG_CFG, " failed to parse CERT RR, skipping"); + continue; + } + + if (cur_crt->get_cert_type(cur_crt) != DNSCERT_TYPE_PKIX && + cur_crt->get_cert_type(cur_crt) != DNSCERT_TYPE_PGP) + { + DBG1(DBG_CFG, " unsupported CERT type [%d], skipping", + cur_crt->get_cert_type(cur_crt)); + cur_crt->destroy(cur_crt); + continue; + } + /* Try to parse PEM certificate container. Both x509 and PGP should + * presumably come as PEM encoded certs. */ + certificate = cur_crt->get_certificate(cur_crt); + *cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_ANY, + BUILD_BLOB_PEM, certificate, + BUILD_END); + if (*cert == NULL) + { + DBG1(DBG_CFG, " unable to parse certificate, skipping", + cur_crt->get_cert_type(cur_crt)); + cur_crt->destroy(cur_crt); + continue; + } + cur_crt->destroy(cur_crt); + return TRUE; + } + return FALSE; +} + +METHOD(enumerator_t, cert_enumerator_destroy, void, + cert_enumerator_t *this) +{ + this->inner->destroy(this->inner); + this->response->destroy(this->response); + free(this); +} + +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_dnscert_cred_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + resolver_response_t *response; + cert_enumerator_t *e; + char *fqdn; + + if (!id || id->get_type(id) != ID_FQDN) + { + return enumerator_create_empty(); + } + + /* query the DNS for the required CERT RRs */ + if (asprintf(&fqdn, "%Y", id) <= 0) + { + DBG1(DBG_CFG, "failed to determine FQDN to retrieve CERT RRs"); + return enumerator_create_empty(); + } + + DBG1(DBG_CFG, "performing a DNS query for CERT RRs of '%s'", fqdn); + response = this->res->query(this->res, fqdn, RR_CLASS_IN, RR_TYPE_CERT); + if (!response) + { + DBG1(DBG_CFG, " query for CERT RRs failed"); + free(fqdn); + return enumerator_create_empty(); + } + free(fqdn); + + if (!response->has_data(response) || + !response->query_name_exist(response)) + { + DBG1(DBG_CFG, " unable to retrieve CERT RRs from the DNS"); + response->destroy(response); + return enumerator_create_empty(); + } + + if (response->get_security_state(response) != SECURE) + { + DBG1(DBG_CFG, " DNSSEC state of CERT RRs is not secure"); + response->destroy(response); + return enumerator_create_empty(); + } + + INIT(e, + .public = { + .enumerate = (void*)_cert_enumerator_enumerate, + .destroy = _cert_enumerator_destroy, + }, + .inner = response->get_rr_set(response)->create_rr_enumerator( + response->get_rr_set(response)), + .response = response + ); + return &e->public; +} + +METHOD(dnscert_cred_t, destroy, void, + private_dnscert_cred_t *this) +{ + this->res->destroy(this->res); + free(this); +} + +/** + * Described in header. + */ +dnscert_cred_t *dnscert_cred_create(resolver_t *res) +{ + private_dnscert_cred_t *this; + + INIT(this, + .public = { + .set = { + .create_private_enumerator = (void*)return_null, + .create_cert_enumerator = _create_cert_enumerator, + .create_shared_enumerator = (void*)return_null, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)nop, + }, + .destroy = _destroy, + }, + .res = res, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/dnscert/dnscert_cred.h b/src/libcharon/plugins/dnscert/dnscert_cred.h new file mode 100644 index 000000000..ceaa68f09 --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert_cred.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup dnscert_cred_i dnscert_cred + * @{ @ingroup dnscert + */ + +#ifndef DNSCERT_CRED_H_ +#define DNSCERT_CRED_H_ + +#include +#include + +typedef struct dnscert_cred_t dnscert_cred_t; + +/** + * DNSCERT credential set. + * + * The dnscert credential set contains CERT RRs as certificates. + */ +struct dnscert_cred_t { + + /** + * Implements credential_set_t interface + */ + credential_set_t set; + + /** + * Destroy the dnscert_cred. + */ + void (*destroy)(dnscert_cred_t *this); +}; + +/** + * Create a dnscert_cred instance which uses the given resolver + * to query the DNS for CERT resource records. + * + * @param res resolver to use (gets adopted) + * @return credential set + */ +dnscert_cred_t *dnscert_cred_create(resolver_t *res); + +#endif /** DNSCERT_CRED_H_ @}*/ diff --git a/src/libcharon/plugins/dnscert/dnscert_plugin.c b/src/libcharon/plugins/dnscert/dnscert_plugin.c new file mode 100644 index 000000000..713bc9e3b --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert_plugin.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * Copyright (C) 2012 Reto Guadagnini + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +#include "dnscert_plugin.h" + +#include +#include "dnscert_cred.h" + +typedef struct private_dnscert_plugin_t private_dnscert_plugin_t; + + +/** + * private data of the dnscert plugin + */ +struct private_dnscert_plugin_t { + + /** + * implements plugin interface + */ + dnscert_plugin_t public; + + /** + * credential set + */ + dnscert_cred_t *cred; + + /** + * DNSCERT based authentication enabled + */ + bool enabled; +}; + +METHOD(plugin_t, get_name, char*, + private_dnscert_plugin_t *this) +{ + return "dnscert"; +} + +METHOD(plugin_t, reload, bool, + private_dnscert_plugin_t *this) +{ + bool enabled = lib->settings->get_bool(lib->settings, + "%s.plugins.dnscert.enable", FALSE, charon->name); + + if (enabled != this->enabled) + { + if (enabled) + { + lib->credmgr->add_set(lib->credmgr, &this->cred->set); + } + else + { + lib->credmgr->remove_set(lib->credmgr, &this->cred->set); + } + this->enabled = enabled; + } + DBG1(DBG_CFG, "dnscert plugin is %sabled", this->enabled ? "en" : "dis"); + return TRUE; +} + +/** + * Create resolver and register credential set + */ +static bool plugin_cb(private_dnscert_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + resolver_t *res; + + res = lib->resolver->create(lib->resolver); + if (!res) + { + DBG1(DBG_CFG, "failed to create a DNS resolver instance"); + return FALSE; + } + + this->cred = dnscert_cred_create(res); + reload(this); + } + else + { + if (this->enabled) + { + lib->credmgr->remove_set(lib->credmgr, &this->cred->set); + } + this->cred->destroy(this->cred); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_dnscert_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "dnscert"), + PLUGIN_DEPENDS(RESOLVER), + PLUGIN_DEPENDS(CERT_DECODE, CERT_ANY), + PLUGIN_SDEPEND(CERT_DECODE, CERT_X509), + PLUGIN_SDEPEND(CERT_DECODE, CERT_GPG), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_dnscert_plugin_t *this) +{ + free(this); +} + +/* + * see header file + */ +plugin_t *dnscert_plugin_create() +{ + private_dnscert_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .reload = _reload, + .destroy = _destroy, + }, + }, + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/dnscert/dnscert_plugin.h b/src/libcharon/plugins/dnscert/dnscert_plugin.h new file mode 100644 index 000000000..79ea64e40 --- /dev/null +++ b/src/libcharon/plugins/dnscert/dnscert_plugin.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2013 Ruslan Marchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @defgroup dnscert dnscert + * @ingroup cplugins + * + * @defgroup dnscert_plugin dnscert_plugin + * @{ @ingroup dnscert + */ + +#ifndef DNSCERT_PLUGIN_H_ +#define DNSCERT_PLUGIN_H_ + +#include + +typedef struct dnscert_plugin_t dnscert_plugin_t; + +/** + * DNSCERT plugin + * + * The DNSCERT plugin registers a credential set for CERT RRs. + * + * With this credential set it is possible to authenticate tunnel endpoints + * using CERT resource records which are retrieved from the DNS in a secure + * way (DNSSEC). + */ +struct dnscert_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** DNSCERT_PLUGIN_H_ @}*/