diff options
Diffstat (limited to 'src/libstrongswan')
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, ¬_before, ¬_after)) + { + DBG1(DBG_CFG, "%s certificate invalid (valid from %T to %T)", + label, ¬_before, FALSE, ¬_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, ¬_before, ¬_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)", - ¬_before, FALSE, ¬_after, FALSE); - return FALSE; - } - if (!issuer->get_validity(issuer, NULL, ¬_before, ¬_after)) - { - DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)", - ¬_before, FALSE, ¬_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, ¤t)) + { + 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 |