diff options
Diffstat (limited to 'src/libstrongswan/plugins')
30 files changed, 1326 insertions, 17 deletions
diff --git a/src/libstrongswan/plugins/ccm/ccm_aead.h b/src/libstrongswan/plugins/ccm/ccm_aead.h index d5e302f94..79ab31804 100644 --- a/src/libstrongswan/plugins/ccm/ccm_aead.h +++ b/src/libstrongswan/plugins/ccm/ccm_aead.h @@ -42,8 +42,8 @@ struct ccm_aead_t { /** * Create a ccm_aead instance. * - * @param key_size key size in bytes * @param algo algorithm to implement, a CCM mode + * @param key_size key size in bytes * @return aead, NULL if not supported */ ccm_aead_t *ccm_aead_create(encryption_algorithm_t algo, size_t key_size); diff --git a/src/libstrongswan/plugins/curl/curl_fetcher.c b/src/libstrongswan/plugins/curl/curl_fetcher.c index c68b74f96..b49961a90 100644 --- a/src/libstrongswan/plugins/curl/curl_fetcher.c +++ b/src/libstrongswan/plugins/curl/curl_fetcher.c @@ -21,7 +21,7 @@ #include "curl_fetcher.h" -#define DEFAULT_TIMEOUT 10 +#define CONNECT_TIMEOUT 10 typedef struct private_curl_fetcher_t private_curl_fetcher_t; @@ -48,6 +48,11 @@ struct private_curl_fetcher_t { * Callback function */ fetcher_callback_t cb; + + /** + * Timeout for a transfer + */ + long timeout; }; /** @@ -94,7 +99,11 @@ METHOD(fetcher_t, fetch, status_t, curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, error); curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE); - curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, DEFAULT_TIMEOUT); + if (this->timeout) + { + curl_easy_setopt(this->curl, CURLOPT_TIMEOUT, this->timeout); + } + curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, CONNECT_TIMEOUT); curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, (void*)curl_cb); curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, &data); if (this->headers) @@ -160,8 +169,7 @@ METHOD(fetcher_t, set_option, bool, } case FETCH_TIMEOUT: { - curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, - va_arg(args, u_int)); + this->timeout = va_arg(args, u_int); break; } case FETCH_CALLBACK: @@ -211,4 +219,3 @@ curl_fetcher_t *curl_fetcher_create() } return &this->public; } - diff --git a/src/libstrongswan/plugins/dnskey/Makefile.am b/src/libstrongswan/plugins/dnskey/Makefile.am index fbba95e0a..0f2e554c1 100644 --- a/src/libstrongswan/plugins/dnskey/Makefile.am +++ b/src/libstrongswan/plugins/dnskey/Makefile.am @@ -11,6 +11,7 @@ endif libstrongswan_dnskey_la_SOURCES = \ dnskey_plugin.h dnskey_plugin.c \ - dnskey_builder.h dnskey_builder.c + dnskey_builder.h dnskey_builder.c \ + dnskey_encoder.h dnskey_encoder.c libstrongswan_dnskey_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/dnskey/dnskey_builder.c b/src/libstrongswan/plugins/dnskey/dnskey_builder.c index b8a451500..71040437d 100644 --- a/src/libstrongswan/plugins/dnskey/dnskey_builder.c +++ b/src/libstrongswan/plugins/dnskey/dnskey_builder.c @@ -39,8 +39,14 @@ enum dnskey_algorithm_t { DNSKEY_ALG_RSA_MD5 = 1, DNSKEY_ALG_DH = 2, DNSKEY_ALG_DSA = 3, - DNSKEY_ALG_ECC = 4, DNSKEY_ALG_RSA_SHA1 = 5, + DNSKEY_ALG_DSA_NSEC3_SHA1 = 6, + DNSKEY_ALG_RSA_SHA1_NSEC3_SHA1 = 7, + DNSKEY_ALG_RSA_SHA256 = 8, + DNSKEY_ALG_RSA_SHA512 = 10, + DNSKEY_ALG_ECC_GOST = 12, + DNSKEY_ALG_ECDSA_P256_SHA256 = 13, + DNSKEY_ALG_ECDSA_P384_SHA384 = 14 }; /** @@ -59,7 +65,11 @@ static dnskey_public_key_t *parse_public_key(chunk_t blob) switch (rr->algorithm) { + case DNSKEY_ALG_RSA_MD5: case DNSKEY_ALG_RSA_SHA1: + case DNSKEY_ALG_RSA_SHA1_NSEC3_SHA1: + case DNSKEY_ALG_RSA_SHA256: + case DNSKEY_ALG_RSA_SHA512: return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_DNSKEY, blob, BUILD_END); default: diff --git a/src/libstrongswan/plugins/dnskey/dnskey_encoder.c b/src/libstrongswan/plugins/dnskey/dnskey_encoder.c new file mode 100644 index 000000000..d2b9894b8 --- /dev/null +++ b/src/libstrongswan/plugins/dnskey/dnskey_encoder.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2013 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <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. + */ + +#include "dnskey_encoder.h" + +#include <utils/debug.h> + +/** + * Encode an RSA public key in DNSKEY format (RFC 3110) + */ +bool build_pub(chunk_t *encoding, va_list args) +{ + chunk_t n, e, pubkey; + size_t exp_len; + u_char *pos; + + if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n, + CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END)) + { + /* remove leading zeros in exponent and modulus */ + while (*e.ptr == 0) + { + e = chunk_skip(e, 1); + } + while (*n.ptr == 0) + { + n = chunk_skip(n, 1); + } + + if (e.len < 256) + { + /* exponent length fits into a single octet */ + exp_len = 1; + pubkey = chunk_alloc(exp_len + e.len + n.len); + pubkey.ptr[0] = (char)e.len; + } + else if (e.len < 65536) + { + /* exponent length fits into two octets preceded by zero octet */ + exp_len = 3; + pubkey = chunk_alloc(exp_len + e.len + n.len); + pubkey.ptr[0] = 0x00; + htoun16(pubkey.ptr + 1, e.len); + } + else + { + /* exponent length is too large */ + return FALSE; + } + + /* copy exponent and modulus and convert to base64 format */ + pos = pubkey.ptr + exp_len; + memcpy(pos, e.ptr, e.len); + pos += e.len; + memcpy(pos, n.ptr, n.len); + *encoding = chunk_to_base64(pubkey, NULL); + chunk_free(&pubkey); + + return TRUE; + } + return FALSE; +} + +/** + * See header. + */ +bool dnskey_encoder_encode(cred_encoding_type_t type, chunk_t *encoding, + va_list args) +{ + switch (type) + { + case PUBKEY_DNSKEY: + return build_pub(encoding, args); + default: + return FALSE; + } +} + + diff --git a/src/libstrongswan/plugins/dnskey/dnskey_encoder.h b/src/libstrongswan/plugins/dnskey/dnskey_encoder.h new file mode 100644 index 000000000..698d29301 --- /dev/null +++ b/src/libstrongswan/plugins/dnskey/dnskey_encoder.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <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. + */ + +/** + * @defgroup dnskey_encoder dnskey_encoder + * @{ @ingroup dnskey + */ + +#ifndef DNSKEY_ENCODER_H_ +#define DNSKEY_ENCODER_H_ + +#include <credentials/cred_encoding.h> + +/** + * Encoding function for DNSKEY (RFC 3110) public key format. + */ +bool dnskey_encoder_encode(cred_encoding_type_t type, chunk_t *encoding, + va_list args); + +#endif /** DNSKEY_ENCODER_H_ @}*/ diff --git a/src/libstrongswan/plugins/dnskey/dnskey_plugin.c b/src/libstrongswan/plugins/dnskey/dnskey_plugin.c index b6863e8e3..9a4f6252f 100644 --- a/src/libstrongswan/plugins/dnskey/dnskey_plugin.c +++ b/src/libstrongswan/plugins/dnskey/dnskey_plugin.c @@ -17,6 +17,7 @@ #include <library.h> #include "dnskey_builder.h" +#include "dnskey_encoder.h" typedef struct private_dnskey_plugin_t private_dnskey_plugin_t; @@ -53,6 +54,8 @@ METHOD(plugin_t, get_features, int, METHOD(plugin_t, destroy, void, private_dnskey_plugin_t *this) { + lib->encoding->remove_encoder(lib->encoding, dnskey_encoder_encode); + free(this); } @@ -73,6 +76,8 @@ plugin_t *dnskey_plugin_create() }, ); + lib->encoding->add_encoder(lib->encoding, dnskey_encoder_encode); + return &this->public.plugin; } diff --git a/src/libstrongswan/plugins/gcm/gcm_aead.h b/src/libstrongswan/plugins/gcm/gcm_aead.h index db4be2442..846c3c76c 100644 --- a/src/libstrongswan/plugins/gcm/gcm_aead.h +++ b/src/libstrongswan/plugins/gcm/gcm_aead.h @@ -42,8 +42,8 @@ struct gcm_aead_t { /** * Create a gcm_aead instance. * - * @param key_size key size in bytes * @param algo algorithm to implement, a gcm mode + * @param key_size key size in bytes * @return aead, NULL if not supported */ gcm_aead_t *gcm_aead_create(encryption_algorithm_t algo, size_t key_size); diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am index f971a5e08..e71567311 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.am +++ b/src/libstrongswan/plugins/openssl/Makefile.am @@ -25,7 +25,8 @@ libstrongswan_openssl_la_SOURCES = \ openssl_crl.c openssl_crl.h \ openssl_pkcs7.c openssl_pkcs7.h \ openssl_rng.c openssl_rng.h \ - openssl_hmac.c openssl_hmac.h + openssl_hmac.c openssl_hmac.h \ + openssl_gcm.c openssl_gcm.h libstrongswan_openssl_la_LDFLAGS = -module -avoid-version libstrongswan_openssl_la_LIBADD = -lcrypto diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c index 4dc5663f1..ff3382473 100644 --- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c @@ -14,6 +14,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_DH + #include <openssl/dh.h> #include "openssl_diffie_hellman.h" @@ -193,3 +197,5 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create( return &this->public; } + +#endif /* OPENSSL_NO_DH */ diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c index d350d050b..12f264267 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c @@ -16,7 +16,7 @@ #include <openssl/opensslconf.h> -#ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_ECDSA #include "openssl_ec_private_key.h" #include "openssl_ec_public_key.h" @@ -423,5 +423,4 @@ error: destroy(this); return NULL; } -#endif /* OPENSSL_NO_EC */ - +#endif /* OPENSSL_NO_ECDSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c index 3f5125b31..c8a45f79a 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c @@ -16,7 +16,7 @@ #include <openssl/opensslconf.h> -#ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_ECDSA #include "openssl_ec_public_key.h" #include "openssl_util.h" @@ -360,5 +360,5 @@ openssl_ec_public_key_t *openssl_ec_public_key_load(key_type_t type, } return &this->public; } -#endif /* OPENSSL_NO_EC */ +#endif /* OPENSSL_NO_ECDSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_gcm.c b/src/libstrongswan/plugins/openssl/openssl_gcm.c new file mode 100644 index 000000000..fde7ae71d --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_gcm.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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. + */ + +#include "openssl_gcm.h" + +#include <openssl/evp.h> + +/** as defined in RFC 4106 */ +#define IV_LEN 8 +#define SALT_LEN 4 +#define NONCE_LEN (IV_LEN + SALT_LEN) + +typedef struct private_aead_t private_aead_t; + +/** + * Private data of aead_t + */ +struct private_aead_t { + + /** + * Public interface + */ + aead_t public; + + /** + * The encryption key + */ + chunk_t key; + + /** + * Salt value + */ + char salt[SALT_LEN]; + + /** + * Size of the integrity check value + */ + size_t icv_size; + + /** + * The cipher to use + */ + const EVP_CIPHER *cipher; +}; + +/** + * Do the actual en/decryption in an EVP context + */ +static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv, + u_char *out, int enc) +{ + EVP_CIPHER_CTX ctx; + u_char nonce[NONCE_LEN]; + bool success = FALSE; + int len; + + memcpy(nonce, this->salt, SALT_LEN); + memcpy(nonce + SALT_LEN, iv.ptr, IV_LEN); + + EVP_CIPHER_CTX_init(&ctx); + EVP_CIPHER_CTX_set_padding(&ctx, 0); + if (!EVP_CipherInit_ex(&ctx, this->cipher, NULL, NULL, NULL, enc) || + !EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, NONCE_LEN, NULL) || + !EVP_CipherInit_ex(&ctx, NULL, NULL, this->key.ptr, nonce, enc)) + { + goto done; + } + if (!enc && !EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, this->icv_size, + data.ptr + data.len)) + { /* set ICV for verification on decryption */ + goto done; + } + if (assoc.len && !EVP_CipherUpdate(&ctx, NULL, &len, assoc.ptr, assoc.len)) + { /* set AAD if specified */ + goto done; + } + if (!EVP_CipherUpdate(&ctx, out, &len, data.ptr, data.len) || + !EVP_CipherFinal_ex(&ctx, out + len, &len)) + { /* EVP_CipherFinal_ex fails if ICV is incorrect on decryption */ + goto done; + } + if (enc && !EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, this->icv_size, + out + data.len)) + { /* copy back the ICV when encrypting */ + goto done; + } + success = TRUE; + +done: + EVP_CIPHER_CTX_cleanup(&ctx); + return success; +} + +METHOD(aead_t, encrypt, bool, + private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv, + chunk_t *encrypted) +{ + u_char *out; + + out = plain.ptr; + if (encrypted) + { + *encrypted = chunk_alloc(plain.len + this->icv_size); + out = encrypted->ptr; + } + return crypt(this, plain, assoc, iv, out, 1); +} + +METHOD(aead_t, decrypt, bool, + private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv, + chunk_t *plain) +{ + u_char *out; + + if (encrypted.len < this->icv_size) + { + return FALSE; + } + encrypted.len -= this->icv_size; + + out = encrypted.ptr; + if (plain) + { + *plain = chunk_alloc(encrypted.len); + out = plain->ptr; + } + return crypt(this, encrypted, assoc, iv, out, 0); +} + +METHOD(aead_t, get_block_size, size_t, + private_aead_t *this) +{ + return this->cipher->block_size; +} + +METHOD(aead_t, get_icv_size, size_t, + private_aead_t *this) +{ + return this->icv_size; +} + +METHOD(aead_t, get_iv_size, size_t, + private_aead_t *this) +{ + return IV_LEN; +} + +METHOD(aead_t, get_key_size, size_t, + private_aead_t *this) +{ + return this->key.len + SALT_LEN; +} + +METHOD(aead_t, set_key, bool, + private_aead_t *this, chunk_t key) +{ + if (key.len != get_key_size(this)) + { + return FALSE; + } + memcpy(this->salt, key.ptr + key.len - SALT_LEN, SALT_LEN); + memcpy(this->key.ptr, key.ptr, this->key.len); + return TRUE; +} + +METHOD(aead_t, destroy, void, + private_aead_t *this) +{ + chunk_clear(&this->key); + free(this); +} + +/* + * Described in header + */ +aead_t *openssl_gcm_create(encryption_algorithm_t algo, size_t key_size) +{ + private_aead_t *this; + + INIT(this, + .public = { + .encrypt = _encrypt, + .decrypt = _decrypt, + .get_block_size = _get_block_size, + .get_icv_size = _get_icv_size, + .get_iv_size = _get_iv_size, + .get_key_size = _get_key_size, + .set_key = _set_key, + .destroy = _destroy, + }, + ); + + switch (algo) + { + case ENCR_AES_GCM_ICV8: + this->icv_size = 8; + break; + case ENCR_AES_GCM_ICV12: + this->icv_size = 12; + break; + case ENCR_AES_GCM_ICV16: + this->icv_size = 16; + break; + default: + free(this); + return NULL; + } + + switch (algo) + { + case ENCR_AES_GCM_ICV8: + case ENCR_AES_GCM_ICV12: + case ENCR_AES_GCM_ICV16: + switch (key_size) + { + case 0: + key_size = 16; + /* FALL */ + case 16: + this->cipher = EVP_get_cipherbyname("aes-128-gcm"); + break; + case 24: + this->cipher = EVP_get_cipherbyname("aes-192-gcm"); + break; + case 32: + this->cipher = EVP_get_cipherbyname("aes-256-gcm"); + break; + default: + free(this); + return NULL; + } + break; + default: + free(this); + return NULL; + } + + if (!this->cipher) + { + free(this); + return NULL; + } + + this->key = chunk_alloc(key_size); + + return &this->public; +} diff --git a/src/libstrongswan/plugins/openssl/openssl_gcm.h b/src/libstrongswan/plugins/openssl/openssl_gcm.h new file mode 100644 index 000000000..12d2e8ab6 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_gcm.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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. + */ + +/** + * Implements the aead_t interface using OpenSSL in GCM mode. + * + * @defgroup openssl_gcm openssl_gcm + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_GCM_H_ +#define OPENSSL_GCM_H_ + +#include <crypto/aead.h> + +/** + * Constructor to create aead_t implementation. + * + * @param algo algorithm to implement + * @param key_size key size in bytes + * @return aead_t object, NULL if not supported + */ +aead_t *openssl_gcm_create(encryption_algorithm_t algo, size_t key_size); + +#endif /** OPENSSL_GCM_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.c b/src/libstrongswan/plugins/openssl/openssl_hmac.c index 5d05425d3..4f0bcc7c3 100644 --- a/src/libstrongswan/plugins/openssl/openssl_hmac.c +++ b/src/libstrongswan/plugins/openssl/openssl_hmac.c @@ -35,6 +35,10 @@ * THE SOFTWARE. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_HMAC + #include <openssl/evp.h> #include <openssl/hmac.h> @@ -189,3 +193,4 @@ signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo) return NULL; } +#endif /* OPENSSL_NO_HMAC */ diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c index ccc426235..9c3c4040c 100644 --- a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c +++ b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c @@ -13,8 +13,10 @@ * for more details. */ +#include <openssl/opensslv.h> #include <openssl/opensslconf.h> +#if OPENSSL_VERSION_NUMBER >= 0x0090807fL #ifndef OPENSSL_NO_CMS #include "openssl_pkcs7.h" @@ -788,3 +790,4 @@ pkcs7_t *openssl_pkcs7_load(container_type_t type, va_list args) } #endif /* OPENSSL_NO_CMS */ +#endif /* OPENSSL_VERSION_NUMBER */ diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index dd6a379d2..282fe2b1b 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -43,6 +43,7 @@ #include "openssl_pkcs7.h" #include "openssl_rng.h" #include "openssl_hmac.h" +#include "openssl_gcm.h" typedef struct private_openssl_plugin_t private_openssl_plugin_t; @@ -304,6 +305,19 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_256), #endif #endif /* OPENSSL_NO_HMAC */ +#ifndef OPENSSL_NO_AES + /* AES GCM */ + PLUGIN_REGISTER(AEAD, openssl_gcm_create), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 32), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 32), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 32), +#endif /* OPENSSL_NO_AES */ #ifndef OPENSSL_NO_DH /* MODP DH groups */ PLUGIN_REGISTER(DH, openssl_diffie_hellman_create), @@ -366,10 +380,12 @@ METHOD(plugin_t, get_features, int, PLUGIN_SDEPEND(PUBKEY, KEY_DSA), PLUGIN_REGISTER(CERT_DECODE, openssl_crl_load, TRUE), PLUGIN_PROVIDE(CERT_DECODE, CERT_X509_CRL), +#if OPENSSL_VERSION_NUMBER >= 0x0090807fL #ifndef OPENSSL_NO_CMS PLUGIN_REGISTER(CONTAINER_DECODE, openssl_pkcs7_load, TRUE), PLUGIN_PROVIDE(CONTAINER_DECODE, CONTAINER_PKCS7), #endif /* OPENSSL_NO_CMS */ +#endif /* OPENSSL_VERSION_NUMBER */ #ifndef OPENSSL_NO_ECDH /* EC DH groups */ PLUGIN_REGISTER(DH, openssl_ec_diffie_hellman_create), @@ -470,4 +486,3 @@ plugin_t *openssl_plugin_create() return &this->public.plugin; } - diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index 926e5928c..fb86a6bf1 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -14,6 +14,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_RSA + #include "openssl_rsa_private_key.h" #include "openssl_rsa_public_key.h" @@ -599,3 +603,4 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type, #endif /* OPENSSL_NO_ENGINE */ } +#endif /* OPENSSL_NO_RSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index 0da5d2514..bf71d7901 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -14,6 +14,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_RSA + #include "openssl_rsa_public_key.h" #include <utils/debug.h> @@ -388,3 +392,5 @@ openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type, destroy(this); return NULL; } + +#endif /* OPENSSL_NO_RSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c index 8501e2cd4..8c00e6a57 100644 --- a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c +++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c @@ -13,6 +13,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_SHA1 + #include "openssl_sha1_prf.h" #include <openssl/sha.h> @@ -143,3 +147,4 @@ openssl_sha1_prf_t *openssl_sha1_prf_create(pseudo_random_function_t algo) return &this->public; } +#endif /* OPENSSL_NO_SHA1 */ diff --git a/src/libstrongswan/plugins/rdrand/rdrand_rng.h b/src/libstrongswan/plugins/rdrand/rdrand_rng.h index d15a48224..3fb49ce6e 100644 --- a/src/libstrongswan/plugins/rdrand/rdrand_rng.h +++ b/src/libstrongswan/plugins/rdrand/rdrand_rng.h @@ -15,7 +15,7 @@ /** * @defgroup rdrand_rng rdrand_rng - * @{ @ingroup rdrand + * @{ @ingroup rdrand_p */ #ifndef RDRAND_RNG_H_ diff --git a/src/libstrongswan/plugins/unbound/Makefile.am b/src/libstrongswan/plugins/unbound/Makefile.am new file mode 100644 index 000000000..efb313407 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/Makefile.am @@ -0,0 +1,20 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\" + + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-unbound.la +else +plugin_LTLIBRARIES = libstrongswan-unbound.la +endif + +libstrongswan_unbound_la_SOURCES = \ + unbound_plugin.h unbound_plugin.c \ + unbound_resolver.c unbound_resolver.h \ + unbound_rr.h unbound_rr.c \ + unbound_response.h unbound_response.c + +libstrongswan_unbound_la_LDFLAGS = -module -avoid-version +libstrongswan_unbound_la_LIBADD = -lunbound -lldns diff --git a/src/libstrongswan/plugins/unbound/unbound_plugin.c b/src/libstrongswan/plugins/unbound/unbound_plugin.c new file mode 100644 index 000000000..90b95330a --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_plugin.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011-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. + */ + +#include "unbound_plugin.h" + +#include <library.h> +#include "unbound_resolver.h" + +typedef struct private_unbound_plugin_t private_unbound_plugin_t; + +/** + * private data of unbound_plugin + */ +struct private_unbound_plugin_t { + + /** + * public functions + */ + unbound_plugin_t public; +}; + +METHOD(plugin_t, get_name, char*, + private_unbound_plugin_t *this) +{ + return "unbound"; +} + +METHOD(plugin_t, destroy, void, + private_unbound_plugin_t *this) +{ + lib->resolver->remove_resolver(lib->resolver, unbound_resolver_create); + free(this); +} + +/* + * see header file + */ +plugin_t *unbound_plugin_create() +{ + private_unbound_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .destroy = _destroy, + }, + }, + ); + + lib->resolver->add_resolver(lib->resolver, unbound_resolver_create); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/unbound/unbound_plugin.h b/src/libstrongswan/plugins/unbound/unbound_plugin.h new file mode 100644 index 000000000..1f0d36454 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011-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. + */ + +/** + * @defgroup unbound_p unbound + * @ingroup plugins + * + * @defgroup unbound_plugin unbound_plugin + * @{ @ingroup unbound_p + */ + +#ifndef unbound_PLUGIN_H_ +#define unbound_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct unbound_plugin_t unbound_plugin_t; + +/** + * Plugin implementing the resolver interface using the libunbound DNS library. + */ +struct unbound_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** unbound_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/unbound/unbound_resolver.c b/src/libstrongswan/plugins/unbound/unbound_resolver.c new file mode 100644 index 000000000..44a2c764b --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_resolver.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2011-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. + */ + +#include <unbound.h> +#include <errno.h> +#include <ldns/ldns.h> +#include <string.h> + +#include <library.h> +#include <utils/debug.h> + +#include "unbound_resolver.h" +#include "unbound_response.h" + +/* DNS resolver configuration and DNSSEC trust anchors */ +#define RESOLV_CONF_FILE "/etc/resolv.conf" +#define TRUST_ANCHOR_FILE IPSEC_CONFDIR "/ipsec.d/dnssec.keys" + +typedef struct private_resolver_t private_resolver_t; + +/** + * private data of a unbound_resolver_t object. + */ +struct private_resolver_t { + + /** + * Public data + */ + resolver_t public; + + /** + * private unbound resolver handle (unbound context) + */ + struct ub_ctx *ctx; +}; + +/** + * query method implementation + */ +METHOD(resolver_t, query, resolver_response_t*, + private_resolver_t *this, char *domain, rr_class_t rr_class, + rr_type_t rr_type) +{ + unbound_response_t *response = NULL; + struct ub_result *result = NULL; + int ub_retval; + + ub_retval = ub_resolve(this->ctx, domain, rr_type, rr_class, &result); + if (ub_retval) + { + DBG1(DBG_LIB, "unbound resolver error: %s", ub_strerror(ub_retval)); + ub_resolve_free(result); + return NULL; + } + + response = unbound_response_create_frm_libub_response(result); + if (!response) + { + DBG1(DBG_LIB, "unbound resolver failed to create response"); + ub_resolve_free(result); + return NULL; + } + ub_resolve_free(result); + + return (resolver_response_t*)response; +} + +/** + * destroy method implementation + */ +METHOD(resolver_t, destroy, void, + private_resolver_t *this) +{ + ub_ctx_delete(this->ctx); + free(this); +} + +/* + * Described in header. + */ +resolver_t *unbound_resolver_create(void) +{ + private_resolver_t *this; + int ub_retval = 0; + char *resolv_conf_file; + char *trust_anchor_file; + + resolv_conf_file = lib->settings->get_str(lib->settings, + "libstrongswan.plugins.unbound.resolv_conf", + RESOLV_CONF_FILE); + + trust_anchor_file = lib->settings->get_str(lib->settings, + "libstrongswan.plugins.unbound.trust_anchors", + TRUST_ANCHOR_FILE); + + INIT(this, + .public = { + .query = _query, + .destroy = _destroy, + }, + ); + + this->ctx = ub_ctx_create(); + if (!this->ctx) + { + DBG1(DBG_LIB, "failed to create unbound resolver context"); + destroy(this); + return NULL; + } + + DBG1(DBG_CFG, "loading unbound resolver config from '%s'", resolv_conf_file); + ub_retval = ub_ctx_resolvconf(this->ctx, resolv_conf_file); + if (ub_retval) + { + DBG1(DBG_CFG, "failed to read the resolver config: %s (%s)", + 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); + if (ub_retval) + { + DBG1(DBG_CFG, "failed to load trust anchors: %s (%s)", + ub_strerror(ub_retval), strerror(errno)); + } + + return &this->public; +} + diff --git a/src/libstrongswan/plugins/unbound/unbound_resolver.h b/src/libstrongswan/plugins/unbound/unbound_resolver.h new file mode 100644 index 000000000..818a717b8 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_resolver.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011-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. + */ + +/** + * @defgroup unbound_resolver unbound_resolver + * @{ @ingroup unbound_p + */ + +#ifndef unbound_RESOLVER_H_ +#define unbound_RESOLVER_H_ + +/** + * Create a resolver_t instance. + */ +resolver_t *unbound_resolver_create(void); + +#endif /** LIBunbound_RESOLVER_H_ @}*/ diff --git a/src/libstrongswan/plugins/unbound/unbound_response.c b/src/libstrongswan/plugins/unbound/unbound_response.c new file mode 100644 index 000000000..6f6c25e89 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_response.c @@ -0,0 +1,259 @@ +/* + * 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. + */ + +#include <resolver/resolver_response.h> +#include <resolver/rr.h> +#include "unbound_rr.h" +#include "unbound_response.h" + +#include <library.h> +#include <utils/debug.h> + +#include <unbound.h> +#include <ldns/ldns.h> + +typedef struct private_unbound_response_t private_unbound_response_t; + +/** + * private data of an unbound_response_t object. + */ +struct private_unbound_response_t { + + /** + * Public data + */ + unbound_response_t public; + + /** + * Original question string + */ + char* query_name; + + /** + * Canonical name of the response + */ + char* canon_name; + + /** + * Are the some RRs in the RRset of this response? + */ + bool has_data; + + /* + * Does the queried name exist? + */ + bool query_name_exist; + + /** + * DNSSEC security state + */ + dnssec_status_t security_state; + + /** + * RRset + */ + rr_set_t *rr_set; +}; + +METHOD(resolver_response_t, get_query_name, char*, + private_unbound_response_t *this) +{ + return this->query_name; +} + +METHOD(resolver_response_t, get_canon_name, char*, + private_unbound_response_t *this) +{ + return this->canon_name; +} + +METHOD(resolver_response_t, has_data, bool, + private_unbound_response_t *this) +{ + return this->has_data; +} + +METHOD(resolver_response_t, query_name_exist, bool, + private_unbound_response_t *this) +{ + return this->query_name_exist; +} + +METHOD(resolver_response_t, get_security_state, dnssec_status_t, + private_unbound_response_t *this) +{ + return this->security_state; +} + +METHOD(resolver_response_t, get_rr_set, rr_set_t*, + private_unbound_response_t *this) +{ + return this->rr_set; +} + +METHOD(resolver_response_t, destroy, void, + private_unbound_response_t *this) +{ + free(this->query_name); + free(this->canon_name); + DESTROY_IF(this->rr_set); + free(this); +} + +/* + * Described in header. + */ +unbound_response_t *unbound_response_create_frm_libub_response( + struct ub_result *libub_response) +{ + private_unbound_response_t *this = NULL; + + INIT(this, + .public = { + .interface = { + .get_query_name = _get_query_name, + .get_canon_name = _get_canon_name, + .has_data = _has_data, + .query_name_exist = _query_name_exist, + .get_security_state = _get_security_state, + .get_rr_set = _get_rr_set, + .destroy = _destroy, + }, + }, + ); + + this->query_name = strdup(libub_response->qname); + + if (libub_response->canonname) + { + this->canon_name = strdup(libub_response->canonname); + } + + this->has_data = libub_response->havedata; + + this->query_name_exist = !(libub_response->nxdomain); + + if (libub_response->secure) + { + this->security_state = SECURE; + } + else if (libub_response->bogus) + { + this->security_state = BOGUS; + } + else + { + this->security_state = INDETERMINATE; + } + + /** + * Create RRset + */ + if (this->query_name_exist && this->has_data) + { + ldns_pkt *dns_pkt = NULL; + ldns_rr_list *orig_rr_list = NULL; + size_t orig_rr_count; + ldns_rr *orig_rr = NULL; + ldns_rdf *orig_rdf = NULL; + ldns_status status; + linked_list_t *rr_list = NULL, *rrsig_list = NULL; + unbound_rr_t *rr = NULL; + int i; + + /**Parse the received DNS packet using the ldns library */ + status = ldns_wire2pkt(&dns_pkt, libub_response->answer_packet, + libub_response->answer_len); + + if (status != LDNS_STATUS_OK) + { + DBG1(DBG_LIB, "failed to parse DNS packet"); + destroy(this); + return NULL; + } + + /* Create a list with the queried RRs. If there are corresponding RRSIGs + * create also a list with these. + */ + rr_list = linked_list_create(); + + orig_rr_list = ldns_pkt_get_section_clone(dns_pkt, LDNS_SECTION_ANSWER); + orig_rr_count = ldns_rr_list_rr_count(orig_rr_list); + + for (i = 0; i < orig_rr_count; i++) + { + orig_rr = ldns_rr_list_rr(orig_rr_list, i); + + if (ldns_rr_get_type(orig_rr) == libub_response->qtype && + ldns_rr_get_class(orig_rr) == libub_response->qclass) + { + /* RR is part of the queried RRset. + * => add it to the list of Resource Records. + */ + rr = unbound_rr_create_frm_ldns_rr(orig_rr); + if (rr) + { + rr_list->insert_last(rr_list, rr); + } + else + { + DBG1(DBG_LIB, "failed to create RR"); + } + } + + if (ldns_rr_get_type(orig_rr) == LDNS_RR_TYPE_RRSIG) + { + orig_rdf = ldns_rr_rrsig_typecovered(orig_rr); + if (!orig_rdf) + { + DBG1(DBG_LIB, "failed to get the type covered by an RRSIG"); + } + else if (ldns_rdf2native_int16(orig_rdf) == libub_response->qtype) + { + /* The current RR represent a signature (RRSIG) + * which belongs to the queried RRset. + * => add it to the list of signatures. + */ + rr = unbound_rr_create_frm_ldns_rr(orig_rr); + if (rr) + { + if (!rrsig_list) + { + rrsig_list = linked_list_create(); + } + rrsig_list->insert_last(rrsig_list, rr); + } + else + { + DBG1(DBG_LIB, "failed to create RRSIG"); + } + } + else + { + DBG1(DBG_LIB, "failed to determine the RR type " + "covered by RRSIG RR"); + } + } + } + /** + * Create the RRset for which the query was performed. + */ + this->rr_set = rr_set_create(rr_list, rrsig_list); + + ldns_pkt_free(dns_pkt); + ldns_rr_list_free(orig_rr_list); + } + return &this->public; +} diff --git a/src/libstrongswan/plugins/unbound/unbound_response.h b/src/libstrongswan/plugins/unbound/unbound_response.h new file mode 100644 index 000000000..d63ead08b --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_response.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +/** + * @defgroup unbound_response unbound_response + * @{ @ingroup unbound_p + */ + +#ifndef UNBOUND_RESPONSE_H_ +#define UNBOUND_RESPONSE_H_ + +#include <resolver/resolver_response.h> +#include <unbound.h> + +typedef struct unbound_response_t unbound_response_t; + +/** + * Implementation of the resolver_response interface using libunbound. + * + */ +struct unbound_response_t { + + /** + * Implements the resolver_response interface + */ + resolver_response_t interface; +}; + +/** + * Create an unbound_response instance from a response of the unbound library. + * + * @param a response of the unbound library + * @return an unbound_response conforming to the resolver_response + * interface, or NULL on failure + */ +unbound_response_t *unbound_response_create_frm_libub_response( + struct ub_result *libub_response); + +#endif /** UNBOUND_RESPONSE_H_ @}*/ diff --git a/src/libstrongswan/plugins/unbound/unbound_rr.c b/src/libstrongswan/plugins/unbound/unbound_rr.c new file mode 100644 index 000000000..97c3b1933 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_rr.c @@ -0,0 +1,164 @@ +/* + * 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. + */ + +#include <resolver/rr.h> + +#include <library.h> +#include <utils/debug.h> + +#include <stdlib.h> +#include <string.h> + +#include "unbound_rr.h" + +typedef struct private_unbound_rr_t private_unbound_rr_t; + +/** + * private data of an unbound_rr_t object. + */ +struct private_unbound_rr_t { + + /** + * Public data + */ + unbound_rr_t public; + + /** + * Owner name + */ + char* name; + + /** + * Type + */ + rr_type_t type; + + /** + * Class + */ + rr_class_t class; + + /** + * TTL + */ + uint32_t ttl; + + /** + * Size of the rdata field in octets + */ + uint16_t size; + + /** + * RDATA field (array of bytes in network order) + */ + u_char *rdata; +}; + +METHOD(rr_t, get_name, char *, + private_unbound_rr_t *this) +{ + return this->name; +} + +METHOD(rr_t, get_type, rr_type_t, + private_unbound_rr_t *this) +{ + return this->type; +} + +METHOD(rr_t, get_class, rr_class_t, + private_unbound_rr_t *this) +{ + return this->class; +} + +METHOD(rr_t, get_ttl, uint32_t, + private_unbound_rr_t *this) +{ + return this->ttl; +} + +METHOD(rr_t, get_rdata, chunk_t, + private_unbound_rr_t *this) +{ + return chunk_create(this->rdata, this->size); +} + +METHOD(rr_t, destroy, void, + private_unbound_rr_t *this) +{ + free(this->name); + free(this->rdata); + free(this); +} + +/* + * Described in header. + */ +unbound_rr_t *unbound_rr_create_frm_ldns_rr(ldns_rr *rr) +{ + private_unbound_rr_t *this; + ldns_status status; + ldns_buffer *buf; + int i; + + INIT(this, + .public = { + .interface = { + .get_name = _get_name, + .get_type = _get_type, + .get_class = _get_class, + .get_ttl = _get_ttl, + .get_rdata = _get_rdata, + .destroy = _destroy, + }, + }, + ); + + this->name = ldns_rdf2str(ldns_rr_owner(rr)); + if (!this->name) + { + DBG1(DBG_LIB, "failed to parse the owner name of a DNS RR"); + _destroy(this); + return NULL; + } + + this->type = ldns_rr_get_type(rr); + this->class = ldns_rr_get_class(rr); + this->ttl = ldns_rr_ttl(rr); + for(i = 0; i < ldns_rr_rd_count(rr); i++) + { + this->size += ldns_rdf_size(ldns_rr_rdf(rr, i)); + } + + /** + * The ldns library splits the RDATA field of a RR in various rdf. + * Here we reassemble these rdf to get the RDATA field of the RR. + */ + buf = ldns_buffer_new(LDNS_MIN_BUFLEN); + /* The buffer will be resized automatically by ldns_rr_rdata2buffer_wire() */ + status = ldns_rr_rdata2buffer_wire(buf, rr); + + if (status != LDNS_STATUS_OK) + { + DBG1(DBG_LIB, "failed to get the RDATA field of a DNS RR"); + _destroy(this); + return NULL; + } + + this->rdata = ldns_buffer_export(buf); + + return &this->public; +} diff --git a/src/libstrongswan/plugins/unbound/unbound_rr.h b/src/libstrongswan/plugins/unbound/unbound_rr.h new file mode 100644 index 000000000..d7c114f86 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_rr.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/** + * @defgroup unbound_rr unbound_rr + * @{ @ingroup unbound_p + */ + +#ifndef UNBOUND_RR_H_ +#define UNBOUND_RR_H_ + +#include <resolver/rr.h> +#include <ldns/ldns.h> + +typedef struct unbound_rr_t unbound_rr_t; + +/** + * Implementation of the Resource Record interface using libunbound and libldns. + */ +struct unbound_rr_t { + + /** + * Implements the Resource Record interface + */ + rr_t interface; +}; + +/** + * Create an unbound_rr instance from a Resource Record given by + * a ldns_struct_rr from the ldns library. + * + * @return Resource Record, NULL on error + */ +unbound_rr_t *unbound_rr_create_frm_ldns_rr(ldns_rr *rr); + +#endif /** UNBOUND_RR_H_ @}*/ |