aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan')
-rw-r--r--src/libstrongswan/asn1/oid.txt6
-rw-r--r--src/libstrongswan/credentials/auth_cfg.c56
-rw-r--r--src/libstrongswan/credentials/cert_validator.h17
-rw-r--r--src/libstrongswan/credentials/credential_manager.c116
-rw-r--r--src/libstrongswan/crypto/crypto_tester.c5
-rw-r--r--src/libstrongswan/plugins/ccm/ccm_aead.h2
-rw-r--r--src/libstrongswan/plugins/dnskey/dnskey_encoder.h2
-rw-r--r--src/libstrongswan/plugins/gcm/gcm_aead.h2
-rw-r--r--src/libstrongswan/plugins/openssl/Makefile.am3
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_gcm.c265
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_gcm.h37
-rw-r--r--src/libstrongswan/plugins/openssl/openssl_plugin.c16
-rw-r--r--src/libstrongswan/plugins/unbound/unbound_response.h8
-rw-r--r--src/libstrongswan/selectors/traffic_selector.c202
-rw-r--r--src/libstrongswan/selectors/traffic_selector.h15
-rw-r--r--src/libstrongswan/utils/backtrace.c90
-rw-r--r--src/libstrongswan/utils/backtrace.h7
-rw-r--r--src/libstrongswan/utils/capabilities.c38
-rw-r--r--src/libstrongswan/utils/identification.c24
-rw-r--r--src/libstrongswan/utils/identification.h6
-rw-r--r--src/libstrongswan/utils/leak_detective.c2
-rw-r--r--src/libstrongswan/utils/utils.c63
-rw-r--r--src/libstrongswan/utils/utils.h40
23 files changed, 853 insertions, 169 deletions
diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt
index c4677a537..49ef1cdf2 100644
--- a/src/libstrongswan/asn1/oid.txt
+++ b/src/libstrongswan/asn1/oid.txt
@@ -213,7 +213,13 @@
0x08 "timeStamping"
0x09 "ocspSigning" OID_OCSP_SIGNING
0x08 "id-otherNames"
+ 0x01 "personalData"
+ 0x02 "userGroup"
+ 0x03 "id-on-permanentIdentifier"
+ 0x04 "id-on-hardwareModuleName"
0x05 "xmppAddr" OID_XMPP_ADDR
+ 0x06 "id-on-SIM"
+ 0x07 "id-on-dnsSRV"
0x0A "id-aca"
0x01 "authenticationInfo" OID_AUTHENTICATION_INFO
0x02 "accessIdentity" OID_ACCESS_IDENTITY
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c
index a718de3dc..d2d0a7d72 100644
--- a/src/libstrongswan/credentials/auth_cfg.c
+++ b/src/libstrongswan/credentials/auth_cfg.c
@@ -76,7 +76,6 @@ static inline bool is_multi_value_rule(auth_rule_t type)
case AUTH_RULE_AAA_IDENTITY:
case AUTH_RULE_XAUTH_IDENTITY:
case AUTH_RULE_XAUTH_BACKEND:
- case AUTH_RULE_SUBJECT_CERT:
case AUTH_HELPER_SUBJECT_CERT:
case AUTH_HELPER_SUBJECT_HASH_URL:
case AUTH_RULE_MAX:
@@ -84,6 +83,7 @@ static inline bool is_multi_value_rule(auth_rule_t type)
case AUTH_RULE_OCSP_VALIDATION:
case AUTH_RULE_CRL_VALIDATION:
case AUTH_RULE_GROUP:
+ case AUTH_RULE_SUBJECT_CERT:
case AUTH_RULE_CA_CERT:
case AUTH_RULE_IM_CERT:
case AUTH_RULE_CERT_POLICY:
@@ -503,8 +503,9 @@ METHOD(auth_cfg_t, complies, bool,
private_auth_cfg_t *this, auth_cfg_t *constraints, bool log_error)
{
enumerator_t *e1, *e2;
- bool success = TRUE, group_match = FALSE;
+ bool success = TRUE, group_match = FALSE, cert_match = FALSE;
identification_t *require_group = NULL;
+ certificate_t *require_cert = NULL;
signature_scheme_t scheme = SIGN_UNKNOWN;
u_int strength = 0;
auth_rule_t t1, t2;
@@ -542,20 +543,21 @@ METHOD(auth_cfg_t, complies, bool,
}
case AUTH_RULE_SUBJECT_CERT:
{
- certificate_t *c1, *c2;
+ certificate_t *cert;
- c1 = (certificate_t*)value;
- c2 = get(this, AUTH_RULE_SUBJECT_CERT);
- if (!c2 || !c1->equals(c1, c2))
+ /* for certs, a match of a single cert is sufficient */
+ require_cert = (certificate_t*)value;
+
+ e2 = create_enumerator(this);
+ while (e2->enumerate(e2, &t2, &cert))
{
- success = FALSE;
- if (log_error)
+ if (t2 == AUTH_RULE_SUBJECT_CERT &&
+ cert->equals(cert, require_cert))
{
- DBG1(DBG_CFG, "constraint check failed: peer not "
- "authenticated with peer cert '%Y'.",
- c1->get_subject(c1));
+ cert_match = TRUE;
}
}
+ e2->destroy(e2);
break;
}
case AUTH_RULE_CRL_VALIDATION:
@@ -828,6 +830,17 @@ METHOD(auth_cfg_t, complies, bool,
}
return FALSE;
}
+
+ if (require_cert && !cert_match)
+ {
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: peer not "
+ "authenticated with peer cert '%Y'.",
+ require_cert->get_subject(require_cert));
+ }
+ return FALSE;
+ }
return success;
}
@@ -999,14 +1012,15 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
{
enumerator_t *enumerator;
auth_cfg_t *clone;
- entry_t *entry;
+ auth_rule_t type;
+ void *value;
clone = auth_cfg_create();
/* this enumerator skips duplicates for rules we expect only once */
- enumerator = this->entries->create_enumerator(this->entries);
- while (enumerator->enumerate(enumerator, &entry))
+ enumerator = create_enumerator(this);
+ while (enumerator->enumerate(enumerator, &type, &value))
{
- switch (entry->type)
+ switch (type)
{
case AUTH_RULE_IDENTITY:
case AUTH_RULE_EAP_IDENTITY:
@@ -1014,8 +1028,8 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
case AUTH_RULE_GROUP:
case AUTH_RULE_XAUTH_IDENTITY:
{
- identification_t *id = (identification_t*)entry->value;
- clone->add(clone, entry->type, id->clone(id));
+ identification_t *id = (identification_t*)value;
+ clone->add(clone, type, id->clone(id));
break;
}
case AUTH_RULE_CA_CERT:
@@ -1025,8 +1039,8 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
case AUTH_HELPER_SUBJECT_CERT:
case AUTH_HELPER_REVOCATION_CERT:
{
- certificate_t *cert = (certificate_t*)entry->value;
- clone->add(clone, entry->type, cert->get_ref(cert));
+ certificate_t *cert = (certificate_t*)value;
+ clone->add(clone, type, cert->get_ref(cert));
break;
}
case AUTH_RULE_XAUTH_BACKEND:
@@ -1034,7 +1048,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
case AUTH_HELPER_IM_HASH_URL:
case AUTH_HELPER_SUBJECT_HASH_URL:
{
- clone->add(clone, entry->type, strdup(entry->value));
+ clone->add(clone, type, strdup(value));
break;
}
case AUTH_RULE_IDENTITY_LOOSE:
@@ -1046,7 +1060,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*,
case AUTH_RULE_RSA_STRENGTH:
case AUTH_RULE_ECDSA_STRENGTH:
case AUTH_RULE_SIGNATURE_SCHEME:
- clone->add(clone, entry->type, (uintptr_t)entry->value);
+ clone->add(clone, type, (uintptr_t)value);
break;
case AUTH_RULE_MAX:
break;
diff --git a/src/libstrongswan/credentials/cert_validator.h b/src/libstrongswan/credentials/cert_validator.h
index 00e30d7a0..325fa0af3 100644
--- a/src/libstrongswan/credentials/cert_validator.h
+++ b/src/libstrongswan/credentials/cert_validator.h
@@ -35,6 +35,22 @@ typedef struct cert_validator_t cert_validator_t;
struct cert_validator_t {
/**
+ * Check the lifetime of a certificate.
+ *
+ * If this function returns SUCCESS or FAILED, the certificate lifetime is
+ * considered definitely (in-)valid, without asking other validators.
+ * If all registered validaters return NEED_MORE, the default
+ * lifetime check is performed.
+ *
+ * @param cert certificate to check lifetime
+ * @param pathlen the current length of the path bottom-up
+ * @param anchor is certificate trusted root anchor?
+ * @param auth container for resulting authentication info
+ * @return SUCCESS, FAILED or NEED_MORE to ask next validator
+ */
+ status_t (*check_lifetime)(cert_validator_t *this, certificate_t *cert,
+ int pathlen, bool anchor, auth_cfg_t *auth);
+ /**
* Validate a subject certificate in relation to its issuer.
*
* @param subject subject certificate to check
@@ -43,6 +59,7 @@ struct cert_validator_t {
* @param pathlen the current length of the path bottom-up
* @param anchor is issuer trusted root anchor
* @param auth container for resulting authentication info
+ * @return TRUE if subject certificate valid
*/
bool (*validate)(cert_validator_t *this, certificate_t *subject,
certificate_t *issuer, bool online, u_int pathlen,
diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c
index 9e40c5a10..f4cd9b9e6 100644
--- a/src/libstrongswan/credentials/credential_manager.c
+++ b/src/libstrongswan/credentials/credential_manager.c
@@ -515,32 +515,74 @@ static void cache_queue(private_credential_manager_t *this)
}
/**
+ * Use validators to check the lifetime of certificates
+ */
+static bool check_lifetime(private_credential_manager_t *this,
+ certificate_t *cert, char *label,
+ int pathlen, bool trusted, auth_cfg_t *auth)
+{
+ time_t not_before, not_after;
+ cert_validator_t *validator;
+ enumerator_t *enumerator;
+ status_t status = NEED_MORE;
+
+ enumerator = this->validators->create_enumerator(this->validators);
+ while (enumerator->enumerate(enumerator, &validator))
+ {
+ if (!validator->check_lifetime)
+ {
+ continue;
+ }
+ status = validator->check_lifetime(validator, cert,
+ pathlen, trusted, auth);
+ if (status != NEED_MORE)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ switch (status)
+ {
+ case NEED_MORE:
+ if (!cert->get_validity(cert, NULL, &not_before, &not_after))
+ {
+ DBG1(DBG_CFG, "%s certificate invalid (valid from %T to %T)",
+ label, &not_before, FALSE, &not_after, FALSE);
+ return FALSE;
+ }
+ return TRUE;
+ case SUCCESS:
+ return TRUE;
+ case FAILED:
+ default:
+ return FALSE;
+ }
+}
+
+/**
* check a certificate for its lifetime
*/
static bool check_certificate(private_credential_manager_t *this,
certificate_t *subject, certificate_t *issuer, bool online,
int pathlen, bool trusted, auth_cfg_t *auth)
{
- time_t not_before, not_after;
cert_validator_t *validator;
enumerator_t *enumerator;
- if (!subject->get_validity(subject, NULL, &not_before, &not_after))
+ if (!check_lifetime(this, subject, "subject", pathlen, FALSE, auth) ||
+ !check_lifetime(this, issuer, "issuer", pathlen + 1, trusted, auth))
{
- DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
- &not_before, FALSE, &not_after, FALSE);
- return FALSE;
- }
- if (!issuer->get_validity(issuer, NULL, &not_before, &not_after))
- {
- DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
- &not_before, FALSE, &not_after, FALSE);
return FALSE;
}
enumerator = this->validators->create_enumerator(this->validators);
while (enumerator->enumerate(enumerator, &validator))
{
+ if (!validator->validate)
+ {
+ continue;
+ }
if (!validator->validate(validator, subject, issuer,
online, pathlen, trusted, auth))
{
@@ -1041,6 +1083,29 @@ static private_key_t *get_private_by_cert(private_credential_manager_t *this,
return private;
}
+/**
+ * Move the actually used certificate to front, so it gets returned with get()
+ */
+static void prefer_cert(auth_cfg_t *auth, certificate_t *cert)
+{
+ enumerator_t *enumerator;
+ auth_rule_t rule;
+ certificate_t *current;
+
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &rule, &current))
+ {
+ if (rule == AUTH_RULE_SUBJECT_CERT)
+ {
+ current->get_ref(current);
+ auth->replace(auth, enumerator, AUTH_RULE_SUBJECT_CERT, cert);
+ cert = current;
+ }
+ }
+ enumerator->destroy(enumerator);
+ auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert);
+}
+
METHOD(credential_manager_t, get_private, private_key_t*,
private_credential_manager_t *this, key_type_t type, identification_t *id,
auth_cfg_t *auth)
@@ -1049,6 +1114,7 @@ METHOD(credential_manager_t, get_private, private_key_t*,
certificate_t *cert;
private_key_t *private = NULL;
auth_cfg_t *trustchain;
+ auth_rule_t rule;
/* check if this is a lookup by key ID, and do it if so */
if (id && id->get_type(id) == ID_KEY_ID)
@@ -1062,7 +1128,35 @@ METHOD(credential_manager_t, get_private, private_key_t*,
if (auth)
{
- /* if a specific certificate is preferred, check for a matching key */
+ /* try to find a trustchain with one of the configured subject certs */
+ enumerator = auth->create_enumerator(auth);
+ while (enumerator->enumerate(enumerator, &rule, &cert))
+ {
+ if (rule == AUTH_RULE_SUBJECT_CERT)
+ {
+ private = get_private_by_cert(this, cert, type);
+ if (private)
+ {
+ trustchain = build_trustchain(this, cert, auth);
+ if (trustchain)
+ {
+ auth->merge(auth, trustchain, FALSE);
+ prefer_cert(auth, cert->get_ref(cert));
+ trustchain->destroy(trustchain);
+ break;
+ }
+ private->destroy(private);
+ private = NULL;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (private)
+ {
+ return private;
+ }
+
+ /* if none yielded a trustchain, enforce the first configured cert */
cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
if (cert)
{
diff --git a/src/libstrongswan/crypto/crypto_tester.c b/src/libstrongswan/crypto/crypto_tester.c
index 08b226468..12db0961b 100644
--- a/src/libstrongswan/crypto/crypto_tester.c
+++ b/src/libstrongswan/crypto/crypto_tester.c
@@ -451,7 +451,10 @@ METHOD(crypto_tester_t, test_aead, bool,
failure:
aead->destroy(aead);
chunk_free(&cipher);
- chunk_free(&plain);
+ if (plain.ptr != vector->plain)
+ {
+ chunk_free(&plain);
+ }
if (failed)
{
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
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/dnskey/dnskey_encoder.h b/src/libstrongswan/plugins/dnskey/dnskey_encoder.h
index 698d29301..127260308 100644
--- a/src/libstrongswan/plugins/dnskey/dnskey_encoder.h
+++ b/src/libstrongswan/plugins/dnskey/dnskey_encoder.h
@@ -15,7 +15,7 @@
/**
* @defgroup dnskey_encoder dnskey_encoder
- * @{ @ingroup dnskey
+ * @{ @ingroup dnskey_p
*/
#ifndef DNSKEY_ENCODER_H_
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_gcm.c b/src/libstrongswan/plugins/openssl/openssl_gcm.c
new file mode 100644
index 000000000..89d1cd589
--- /dev/null
+++ b/src/libstrongswan/plugins/openssl/openssl_gcm.c
@@ -0,0 +1,265 @@
+/*
+ * 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/opensslv.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x1000100fL
+
+#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;
+}
+
+#endif /* OPENSSL_VERSION_NUMBER */
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_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c
index 0f5b07137..915082234 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,21 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_256),
#endif
#endif /* OPENSSL_NO_HMAC */
+#if OPENSSL_VERSION_NUMBER >= 0x1000100fL
+#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 */
+#endif /* OPENSSL_VERSION_NUMBER */
#ifndef OPENSSL_NO_DH
/* MODP DH groups */
PLUGIN_REGISTER(DH, openssl_diffie_hellman_create),
diff --git a/src/libstrongswan/plugins/unbound/unbound_response.h b/src/libstrongswan/plugins/unbound/unbound_response.h
index d63ead08b..c82f39d45 100644
--- a/src/libstrongswan/plugins/unbound/unbound_response.h
+++ b/src/libstrongswan/plugins/unbound/unbound_response.h
@@ -41,11 +41,11 @@ struct unbound_response_t {
/**
* 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
+ * @param response 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);
+ struct ub_result *response);
#endif /** UNBOUND_RESPONSE_H_ @}*/
diff --git a/src/libstrongswan/selectors/traffic_selector.c b/src/libstrongswan/selectors/traffic_selector.c
index 87e57095c..ff8285f8c 100644
--- a/src/libstrongswan/selectors/traffic_selector.c
+++ b/src/libstrongswan/selectors/traffic_selector.c
@@ -174,7 +174,24 @@ static u_int8_t calc_netbits(private_traffic_selector_t *this)
/**
* internal generic constructor
*/
-static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port);
+static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol,
+ ts_type_t type, u_int16_t from_port, u_int16_t to_port);
+
+/**
+ * Check if TS contains "opaque" ports
+ */
+static bool is_opaque(private_traffic_selector_t *this)
+{
+ return this->from_port == 0xffff && this->to_port == 0;
+}
+
+/**
+ * Check if TS contains "any" ports
+ */
+static bool is_any(private_traffic_selector_t *this)
+{
+ return this->from_port == 0 && this->to_port == 0xffff;
+}
/**
* Described in header.
@@ -248,7 +265,7 @@ int traffic_selector_printf_hook(printf_hook_data_t *data,
/* check if we have protocol and/or port selectors */
has_proto = this->protocol != 0;
- has_ports = !(this->from_port == 0 && this->to_port == 0xFFFF);
+ has_ports = !is_any(this);
if (!has_proto && !has_ports)
{
@@ -283,8 +300,9 @@ int traffic_selector_printf_hook(printf_hook_data_t *data,
{
if (this->from_port == this->to_port)
{
- struct servent *serv = getservbyport(htons(this->from_port), serv_proto);
+ struct servent *serv;
+ serv = getservbyport(htons(this->from_port), serv_proto);
if (serv)
{
written += print_in_hook(data, "%s", serv->s_name);
@@ -294,9 +312,14 @@ int traffic_selector_printf_hook(printf_hook_data_t *data,
written += print_in_hook(data, "%d", this->from_port);
}
}
+ else if (is_opaque(this))
+ {
+ written += print_in_hook(data, "OPAQUE");
+ }
else
{
- written += print_in_hook(data, "%d-%d", this->from_port, this->to_port);
+ written += print_in_hook(data, "%d-%d",
+ this->from_port, this->to_port);
}
}
@@ -305,24 +328,55 @@ int traffic_selector_printf_hook(printf_hook_data_t *data,
return written;
}
-/**
- * Implements traffic_selector_t.get_subset
- */
-static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other)
+METHOD(traffic_selector_t, get_subset, traffic_selector_t*,
+ private_traffic_selector_t *this, traffic_selector_t *other_public)
{
+ private_traffic_selector_t *other, *subset;
+ u_int16_t from_port, to_port;
+ u_char *from, *to;
+ u_int8_t protocol;
+ size_t size;
+
+ other = (private_traffic_selector_t*)other_public;
+
if (this->dynamic || other->dynamic)
{ /* no set_address() applied, TS has no subset */
return NULL;
}
- if (this->type == other->type && (this->protocol == other->protocol ||
- this->protocol == 0 || other->protocol == 0))
+
+ if (this->type != other->type)
+ {
+ return NULL;
+ }
+ switch (this->type)
+ {
+ case TS_IPV4_ADDR_RANGE:
+ size = sizeof(this->from4);
+ break;
+ case TS_IPV6_ADDR_RANGE:
+ size = sizeof(this->from6);
+ break;
+ default:
+ return NULL;
+ }
+
+ if (this->protocol != other->protocol &&
+ this->protocol != 0 && other->protocol != 0)
{
- u_int16_t from_port, to_port;
- u_char *from, *to;
- u_int8_t protocol;
- size_t size;
- private_traffic_selector_t *new_ts;
+ return NULL;
+ }
+ /* select protocol, which is not zero */
+ protocol = max(this->protocol, other->protocol);
+ if ((is_opaque(this) && is_opaque(other)) ||
+ (is_opaque(this) && is_any(other)) ||
+ (is_opaque(other) && is_any(this)))
+ {
+ from_port = 0xffff;
+ to_port = 0;
+ }
+ else
+ {
/* calculate the maximum port range allowed for both */
from_port = max(this->from_port, other->from_port);
to_port = min(this->to_port, other->to_port);
@@ -330,60 +384,46 @@ static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_
{
return NULL;
}
- /* select protocol, which is not zero */
- protocol = max(this->protocol, other->protocol);
-
- switch (this->type)
- {
- case TS_IPV4_ADDR_RANGE:
- size = sizeof(this->from4);
- break;
- case TS_IPV6_ADDR_RANGE:
- size = sizeof(this->from6);
- break;
- default:
- return NULL;
- }
+ }
+ /* get higher from-address */
+ if (memcmp(this->from, other->from, size) > 0)
+ {
+ from = this->from;
+ }
+ else
+ {
+ from = other->from;
+ }
+ /* get lower to-address */
+ if (memcmp(this->to, other->to, size) > 0)
+ {
+ to = other->to;
+ }
+ else
+ {
+ to = this->to;
+ }
+ /* if "from" > "to", we don't have a match */
+ if (memcmp(from, to, size) > 0)
+ {
+ return NULL;
+ }
- /* get higher from-address */
- if (memcmp(this->from, other->from, size) > 0)
- {
- from = this->from;
- }
- else
- {
- from = other->from;
- }
- /* get lower to-address */
- if (memcmp(this->to, other->to, size) > 0)
- {
- to = other->to;
- }
- else
- {
- to = this->to;
- }
- /* if "from" > "to", we don't have a match */
- if (memcmp(from, to, size) > 0)
- {
- return NULL;
- }
+ /* we have a match in protocol, port, and address: return it... */
+ subset = traffic_selector_create(protocol, this->type, from_port, to_port);
+ memcpy(subset->from, from, size);
+ memcpy(subset->to, to, size);
+ calc_netbits(subset);
- /* we have a match in protocol, port, and address: return it... */
- new_ts = traffic_selector_create(protocol, this->type, from_port, to_port);
- memcpy(new_ts->from, from, size);
- memcpy(new_ts->to, to, size);
- calc_netbits(new_ts);
- return &new_ts->public;
- }
- return NULL;
+ return &subset->public;
}
-/**
- * Implements traffic_selector_t.equals
- */
-static bool equals(private_traffic_selector_t *this, private_traffic_selector_t *other)
+METHOD(traffic_selector_t, equals, bool,
+ private_traffic_selector_t *this, traffic_selector_t *other_public)
{
+ private_traffic_selector_t *other;
+
+ other = (private_traffic_selector_t*)other_public;
if (this->type != other->type)
{
return FALSE;
@@ -535,11 +575,8 @@ METHOD(traffic_selector_t, set_address, void,
}
}
-/**
- * Implements traffic_selector_t.is_contained_in.
- */
-static bool is_contained_in(private_traffic_selector_t *this,
- private_traffic_selector_t *other)
+METHOD(traffic_selector_t, is_contained_in, bool,
+ private_traffic_selector_t *this, traffic_selector_t *other)
{
private_traffic_selector_t *subset;
bool contained_in = FALSE;
@@ -548,7 +585,7 @@ static bool is_contained_in(private_traffic_selector_t *this,
if (subset)
{
- if (equals(subset, this))
+ if (equals(subset, &this->public))
{
contained_in = TRUE;
}
@@ -739,12 +776,13 @@ traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
* see header
*/
traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
- u_int8_t netbits, u_int8_t protocol, u_int16_t port)
+ u_int8_t netbits, u_int8_t protocol,
+ u_int16_t from_port, u_int16_t to_port)
{
private_traffic_selector_t *this;
chunk_t from;
- this = traffic_selector_create(protocol, 0, 0, 65535);
+ this = traffic_selector_create(protocol, 0, from_port, to_port);
switch (net->get_family(net))
{
@@ -763,11 +801,6 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net,
memcpy(this->from, from.ptr, from.len);
netbits = min(netbits, this->type == TS_IPV4_ADDR_RANGE ? 32 : 128);
calc_range(this, netbits);
- if (port)
- {
- this->from_port = port;
- this->to_port = port;
- }
net->destroy(net);
return &this->public;
@@ -818,8 +851,9 @@ traffic_selector_t *traffic_selector_create_from_string(
/*
* see header
*/
-traffic_selector_t *traffic_selector_create_from_cidr(char *string,
- u_int8_t protocol, u_int16_t port)
+traffic_selector_t *traffic_selector_create_from_cidr(
+ char *string, u_int8_t protocol,
+ u_int16_t from_port, u_int16_t to_port)
{
host_t *net;
int bits;
@@ -827,7 +861,8 @@ traffic_selector_t *traffic_selector_create_from_cidr(char *string,
net = host_create_from_subnet(string, &bits);
if (net)
{
- return traffic_selector_create_from_subnet(net, bits, protocol, port);
+ return traffic_selector_create_from_subnet(net, bits, protocol,
+ from_port, to_port);
}
return NULL;
}
@@ -859,8 +894,8 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol,
INIT(this,
.public = {
- .get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset,
- .equals = (bool(*)(traffic_selector_t*,traffic_selector_t*))equals,
+ .get_subset = _get_subset,
+ .equals = _equals,
.get_from_address = _get_from_address,
.get_to_address = _get_to_address,
.get_from_port = _get_from_port,
@@ -869,7 +904,7 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol,
.get_protocol = _get_protocol,
.is_host = _is_host,
.is_dynamic = _is_dynamic,
- .is_contained_in = (bool(*)(traffic_selector_t*,traffic_selector_t*))is_contained_in,
+ .is_contained_in = _is_contained_in,
.includes = _includes,
.set_address = _set_address,
.to_subnet = _to_subnet,
@@ -884,4 +919,3 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol,
return this;
}
-
diff --git a/src/libstrongswan/selectors/traffic_selector.h b/src/libstrongswan/selectors/traffic_selector.h
index b6da391aa..0de358b99 100644
--- a/src/libstrongswan/selectors/traffic_selector.h
+++ b/src/libstrongswan/selectors/traffic_selector.h
@@ -238,11 +238,13 @@ traffic_selector_t *traffic_selector_create_from_string(
*
* @param string CIDR string, such as 10.1.0.0/16
* @param protocol protocol for this ts, such as TCP or UDP
- * @param port single port for this TS, 0 for any port
+ * @param from_port start of allowed port range
+ * @param to_port end of port range
* @return traffic selector, NULL if string invalid
*/
-traffic_selector_t *traffic_selector_create_from_cidr(char *string,
- u_int8_t protocol, u_int16_t port);
+traffic_selector_t *traffic_selector_create_from_cidr(
+ char *string, u_int8_t protocol,
+ u_int16_t from_port, u_int16_t to_port);
/**
* Create a new traffic selector using data read from the net.
@@ -288,14 +290,15 @@ traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
* @param net subnet to use
* @param netbits size of the subnet, as used in e.g. 192.168.0.0/24 notation
* @param protocol protocol for this ts, such as TCP or UDP
- * @param port port number, host order
+ * @param from_port start of allowed port range
+ * @param to_port end of port range
* @return
* - traffic_selector_t object
* - NULL if address family of net not supported
*/
traffic_selector_t *traffic_selector_create_from_subnet(
- host_t *net, u_int8_t netbits,
- u_int8_t protocol, u_int16_t port);
+ host_t *net, u_int8_t netbits, u_int8_t protocol,
+ u_int16_t from_port, u_int16_t to_port);
/**
* Create a traffic selector for host-to-host cases.
diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c
index 0b6683233..45571981e 100644
--- a/src/libstrongswan/utils/backtrace.c
+++ b/src/libstrongswan/utils/backtrace.c
@@ -27,6 +27,8 @@
#include "backtrace.h"
+#include <utils/debug.h>
+
typedef struct private_backtrace_t private_backtrace_t;
/**
@@ -50,6 +52,40 @@ struct private_backtrace_t {
void *frames[];
};
+/**
+ * Same as tty_escape_get(), but for a potentially NULL FILE*
+ */
+static char* esc(FILE *file, tty_escape_t escape)
+{
+ if (file)
+ {
+ return tty_escape_get(fileno(file), escape);
+ }
+ return "";
+}
+
+/**
+ * Write a format string with arguments to a FILE line, if it is NULL to DBG
+ */
+static void println(FILE *file, char *format, ...)
+{
+ char buf[512];
+ va_list args;
+
+ va_start(args, format);
+ if (file)
+ {
+ vfprintf(file, format, args);
+ fputs("\n", file);
+ }
+ else
+ {
+ vsnprintf(buf, sizeof(buf), format, args);
+ DBG1(DBG_LIB, "%s", buf);
+ }
+ va_end(args);
+}
+
#ifdef HAVE_DLADDR
#ifdef HAVE_BFD_H
@@ -158,6 +194,7 @@ static void find_addr(bfd *abfd, asection *section, bfd_find_data_t *data)
bfd_vma vma;
const char *source;
const char *function;
+ char fbuf[512] = "", sbuf[512] = "";
u_int line;
if (!data->found || (bfd_get_section_flags(abfd, section) & SEC_ALLOC) != 0)
@@ -175,16 +212,18 @@ static void find_addr(bfd *abfd, asection *section, bfd_find_data_t *data)
{
if (source || function)
{
- fprintf(data->file, " -> ");
if (function)
{
- fprintf(data->file, "\e[34m%s() ", function);
+ snprintf(fbuf, sizeof(fbuf), "%s%s() ",
+ esc(data->file, TTY_FG_BLUE), function);
}
if (source)
{
- fprintf(data->file, "\e[32m@ %s:%d", source, line);
+ snprintf(sbuf, sizeof(sbuf), "%s@ %s:%d",
+ esc(data->file, TTY_FG_GREEN), source, line);
}
- fprintf(data->file, "\e[0m\n");
+ println(data->file, " -> %s%s%s", fbuf, sbuf,
+ esc(data->file, TTY_FG_DEF));
}
}
}
@@ -296,26 +335,28 @@ void backtrace_deinit() {}
*/
static void print_sourceline(FILE *file, char *filename, void *ptr)
{
- char cmd[1024];
+ char buf[1024];
FILE *output;
- int c;
+ int c, i = 0;
- snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", filename, ptr);
- output = popen(cmd, "r");
+ snprintf(buf, sizeof(buf), "addr2line -e %s %p", filename, ptr);
+ output = popen(buf, "r");
if (output)
{
- fprintf(file, " -> \e[32m");
- while (TRUE)
+ while (i < sizeof(buf))
{
c = getc(output);
if (c == '\n' || c == EOF)
{
+ buf[i++] = 0;
break;
}
- fputc(c, file);
+ buf[i++] = c;
}
pclose(output);
- fprintf(file, "\e[0m\n");
+
+ println(file, " -> %s%s%s", esc(file, TTY_FG_GREEN), buf,
+ esc(file, TTY_FG_DEF));
}
}
@@ -337,7 +378,7 @@ METHOD(backtrace_t, log_, void,
strings = backtrace_symbols(this->frames, this->frame_count);
- fprintf(file, " dumping %d stack frame addresses:\n", this->frame_count);
+ println(file, " dumping %d stack frame addresses:", this->frame_count);
for (i = 0; i < this->frame_count; i++)
{
#ifdef HAVE_DLADDR
@@ -353,16 +394,20 @@ METHOD(backtrace_t, log_, void,
}
if (info.dli_sname)
{
- fprintf(file, " \e[33m%s\e[0m @ %p (\e[31m%s\e[0m+0x%tx) [%p]\n",
- info.dli_fname, info.dli_fbase, info.dli_sname,
- this->frames[i] - info.dli_saddr, this->frames[i]);
+ println(file, " %s%s%s @ %p (%s%s%s+0x%tx) [%p]",
+ esc(file, TTY_FG_YELLOW), info.dli_fname,
+ esc(file, TTY_FG_DEF), info.dli_fbase,
+ esc(file, TTY_FG_RED), info.dli_sname,
+ esc(file, TTY_FG_DEF), this->frames[i] - info.dli_saddr,
+ this->frames[i]);
}
else
{
- fprintf(file, " \e[33m%s\e[0m @ %p [%p]\n", info.dli_fname,
- info.dli_fbase, this->frames[i]);
+ println(file, " %s%s%s @ %p [%p]",
+ esc(file, TTY_FG_YELLOW), info.dli_fname,
+ esc(file, TTY_FG_DEF), info.dli_fbase, this->frames[i]);
}
- if (detailed)
+ if (detailed && info.dli_fname[0])
{
print_sourceline(file, (char*)info.dli_fname, ptr);
}
@@ -370,12 +415,12 @@ METHOD(backtrace_t, log_, void,
else
#endif /* HAVE_DLADDR */
{
- fprintf(file, " %s\n", strings[i]);
+ println(file, " %s", strings[i]);
}
}
free (strings);
#else /* !HAVE_BACKTRACE */
- fprintf(file, "C library does not support backtrace().\n");
+ println(file, "C library does not support backtrace().");
#endif /* HAVE_BACKTRACE */
}
@@ -511,9 +556,8 @@ void backtrace_dump(char *label, FILE *file, bool detailed)
if (label)
{
- fprintf(file, "Debug backtrace: %s\n", label);
+ println(file, "Debug backtrace: %s", label);
}
backtrace->log(backtrace, file, detailed);
backtrace->destroy(backtrace);
}
-
diff --git a/src/libstrongswan/utils/backtrace.h b/src/libstrongswan/utils/backtrace.h
index aeeba4dd6..62104238d 100644
--- a/src/libstrongswan/utils/backtrace.h
+++ b/src/libstrongswan/utils/backtrace.h
@@ -35,7 +35,10 @@ struct backtrace_t {
/**
* Log the backtrace to a FILE stream.
*
- * @param file FILE to log backtrace to
+ * If no file pointer is given, the backtrace is reported over the debug
+ * framework to the registered dbg() callback function.
+ *
+ * @param file FILE to log backtrace to, NULL for dbg() function
* @param detailed TRUE to resolve line/file using addr2line (slow)
*/
void (*log)(backtrace_t *this, FILE *file, bool detailed);
@@ -81,7 +84,7 @@ backtrace_t *backtrace_create(int skip);
* Create a backtrace, dump it and clean it up.
*
* @param label description to print for this backtrace, or NULL
- * @param file FILE to log backtrace to
+ * @param file FILE to log backtrace to, NULL to dbg() function
* @param detailed TRUE to resolve line/file using addr2line (slow)
*/
void backtrace_dump(char *label, FILE *file, bool detailed);
diff --git a/src/libstrongswan/utils/capabilities.c b/src/libstrongswan/utils/capabilities.c
index c36a76efe..44a14496c 100644
--- a/src/libstrongswan/utils/capabilities.c
+++ b/src/libstrongswan/utils/capabilities.c
@@ -29,7 +29,9 @@
#include <utils/debug.h>
-#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETGRNAM_R)
+#if !defined(HAVE_GETPWNAM_R) || \
+ !defined(HAVE_GETGRNAM_R) || \
+ !defined(HAVE_GETPWUID_R)
# include <threading/mutex.h>
# define EMULATE_R_FUNCS
#endif
@@ -188,6 +190,34 @@ METHOD(capabilities_t, resolve_gid, bool,
return FALSE;
}
+/**
+ * Initialize supplementary groups for unprivileged user
+ */
+static bool init_supplementary_groups(private_capabilities_t *this)
+{
+ struct passwd *pwp;
+ int res = -1;
+
+#ifdef HAVE_GETPWUID_R
+ struct passwd pwd;
+ char buf[1024];
+
+ if (getpwuid_r(this->uid, &pwd, buf, sizeof(buf), &pwp) == 0 && pwp)
+ {
+ res = initgroups(pwp->pw_name, this->gid);
+ }
+#else /* HAVE_GETPWUID_R */
+ this->mutex->lock(this->mutex);
+ pwp = getpwuid(this->uid);
+ if (pwp)
+ {
+ res = initgroups(pwp->pw_name, this->gid);
+ }
+ this->mutex->unlock(this->mutex);
+#endif /* HAVE_GETPWUID_R */
+ return res == 0;
+}
+
METHOD(capabilities_t, drop, bool,
private_capabilities_t *this)
{
@@ -195,6 +225,12 @@ METHOD(capabilities_t, drop, bool,
prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
#endif
+ if (!init_supplementary_groups(this))
+ {
+ DBG1(DBG_LIB, "initializing supplementary groups for %u failed",
+ this->uid);
+ return FALSE;
+ }
if (this->gid && setgid(this->gid) != 0)
{
DBG1(DBG_LIB, "change to unprivileged group %u failed: %s",
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index 2669c2da6..4176320dc 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -49,10 +49,10 @@ ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID,
"ID_DER_ASN1_DN",
"ID_DER_ASN1_GN",
"ID_KEY_ID");
-ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_MYID, ID_KEY_ID,
+ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_USER_ID, ID_KEY_ID,
"ID_DER_ASN1_GN_URI",
- "ID_MYID");
-ENUM_END(id_type_names, ID_MYID);
+ "ID_USER_ID");
+ENUM_END(id_type_names, ID_USER_ID);
/**
* coding of X.501 distinguished name
@@ -790,6 +790,7 @@ int identification_printf_hook(printf_hook_data_t *data,
case ID_FQDN:
case ID_RFC822_ADDR:
case ID_DER_ASN1_GN_URI:
+ case ID_USER_ID:
chunk_printable(this->encoded, &proper, '?');
snprintf(buf, sizeof(buf), "%.*s", (int)proper.len, proper.ptr);
chunk_free(&proper);
@@ -812,9 +813,6 @@ int identification_printf_hook(printf_hook_data_t *data,
snprintf(buf, sizeof(buf), "%#B", &this->encoded);
}
break;
- case ID_MYID:
- snprintf(buf, sizeof(buf), "%%myid");
- break;
default:
snprintf(buf, sizeof(buf), "(unknown ID type: %d)", this->type);
break;
@@ -873,6 +871,7 @@ static private_identification_t *identification_create(id_type_t type)
break;
case ID_FQDN:
case ID_RFC822_ADDR:
+ case ID_USER_ID:
this->public.matches = _matches_string;
this->public.equals = _equals_strcasecmp;
this->public.contains_wildcards = _contains_wildcards_memchr;
@@ -1023,9 +1022,16 @@ identification_t * identification_create_from_data(chunk_t data)
{
char buf[data.len + 1];
- /* use string constructor */
- snprintf(buf, sizeof(buf), "%.*s", (int)data.len, data.ptr);
- return identification_create_from_string(buf);
+ if (is_asn1(data))
+ {
+ return identification_create_from_encoding(ID_DER_ASN1_DN, data);
+ }
+ else
+ {
+ /* use string constructor */
+ snprintf(buf, sizeof(buf), "%.*s", (int)data.len, data.ptr);
+ return identification_create_from_string(buf);
+ }
}
/*
diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h
index cdf229127..00d740765 100644
--- a/src/libstrongswan/utils/identification.h
+++ b/src/libstrongswan/utils/identification.h
@@ -126,14 +126,14 @@ enum id_type_t {
ID_KEY_ID = 11,
/**
- * private type which represents a GeneralName of type URI
+ * Private ID type which represents a GeneralName of type URI
*/
ID_DER_ASN1_GN_URI = 201,
/**
- * Private ID used by the pluto daemon for opportunistic encryption
+ * Private ID type which represents a user ID
*/
- ID_MYID = 203,
+ ID_USER_ID = 202
};
/**
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index 2b0be1661..6bf4d63cd 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -226,6 +226,8 @@ char *whitelist[] = {
"setpwent",
"endpwent",
"getspnam_r",
+ "getpwuid_r",
+ "initgroups",
/* ignore dlopen, as we do not dlclose to get proper leak reports */
"dlopen",
"dlerror",
diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c
index 0850df9bc..2f38d8a93 100644
--- a/src/libstrongswan/utils/utils.c
+++ b/src/libstrongswan/utils/utils.c
@@ -194,6 +194,69 @@ bool mkdir_p(const char *path, mode_t mode)
return TRUE;
}
+ENUM(tty_color_names, TTY_RESET, TTY_BG_DEF,
+ "\e[0m",
+ "\e[1m",
+ "\e[4m",
+ "\e[5m",
+ "\e[30m",
+ "\e[31m",
+ "\e[32m",
+ "\e[33m",
+ "\e[34m",
+ "\e[35m",
+ "\e[36m",
+ "\e[37m",
+ "\e[39m",
+ "\e[40m",
+ "\e[41m",
+ "\e[42m",
+ "\e[43m",
+ "\e[44m",
+ "\e[45m",
+ "\e[46m",
+ "\e[47m",
+ "\e[49m",
+);
+
+/**
+ * Get the escape string for a given TTY color, empty string on non-tty FILE
+ */
+char* tty_escape_get(int fd, tty_escape_t escape)
+{
+ if (!isatty(fd))
+ {
+ return "";
+ }
+ switch (escape)
+ {
+ case TTY_RESET:
+ case TTY_BOLD:
+ case TTY_UNDERLINE:
+ case TTY_BLINKING:
+ case TTY_FG_BLACK:
+ case TTY_FG_RED:
+ case TTY_FG_GREEN:
+ case TTY_FG_YELLOW:
+ case TTY_FG_BLUE:
+ case TTY_FG_MAGENTA:
+ case TTY_FG_CYAN:
+ case TTY_FG_WHITE:
+ case TTY_FG_DEF:
+ case TTY_BG_BLACK:
+ case TTY_BG_RED:
+ case TTY_BG_GREEN:
+ case TTY_BG_YELLOW:
+ case TTY_BG_BLUE:
+ case TTY_BG_MAGENTA:
+ case TTY_BG_CYAN:
+ case TTY_BG_WHITE:
+ case TTY_BG_DEF:
+ return enum_to_name(tty_color_names, escape);
+ /* warn if a excape code is missing */
+ }
+ return "";
+}
/**
* The size of the thread-specific error buffer
diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h
index 6c24a261f..c66c665e0 100644
--- a/src/libstrongswan/utils/utils.h
+++ b/src/libstrongswan/utils/utils.h
@@ -314,6 +314,46 @@ enum status_t {
*/
extern enum_name_t *status_names;
+typedef enum tty_escape_t tty_escape_t;
+
+/**
+ * Excape codes for tty colors
+ */
+enum tty_escape_t {
+ /** text properties */
+ TTY_RESET,
+ TTY_BOLD,
+ TTY_UNDERLINE,
+ TTY_BLINKING,
+
+ /** foreground colors */
+ TTY_FG_BLACK,
+ TTY_FG_RED,
+ TTY_FG_GREEN,
+ TTY_FG_YELLOW,
+ TTY_FG_BLUE,
+ TTY_FG_MAGENTA,
+ TTY_FG_CYAN,
+ TTY_FG_WHITE,
+ TTY_FG_DEF,
+
+ /** background colors */
+ TTY_BG_BLACK,
+ TTY_BG_RED,
+ TTY_BG_GREEN,
+ TTY_BG_YELLOW,
+ TTY_BG_BLUE,
+ TTY_BG_MAGENTA,
+ TTY_BG_CYAN,
+ TTY_BG_WHITE,
+ TTY_BG_DEF,
+};
+
+/**
+ * Get the escape string for a given TTY color, empty string on non-tty fd
+ */
+char* tty_escape_get(int fd, tty_escape_t escape);
+
/**
* deprecated pluto style return value:
* error message, NULL for success