diff options
author | Martin Willi <martin@strongswan.org> | 2006-06-15 11:09:11 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2006-06-15 11:09:11 +0000 |
commit | c095388f7f04930171eca643f29db972ec7d9ed5 (patch) | |
tree | 07acc62917bfd4a95a3a7fca76afa6431587c974 | |
parent | 3efbf983124b6cd89087a3967bdfdfe0ccc607e3 (diff) | |
download | strongswan-c095388f7f04930171eca643f29db972ec7d9ed5.tar.bz2 strongswan-c095388f7f04930171eca643f29db972ec7d9ed5.tar.xz |
added support for "ike" and "esp" keywords
fixed bugs in proposal code
algorithm selection for charon works now with ipsec.conf
a lot of other fixes
-rw-r--r-- | src/charon/config/connections/connection.c | 10 | ||||
-rw-r--r-- | src/charon/config/proposal.c | 158 | ||||
-rw-r--r-- | src/charon/config/proposal.h | 33 | ||||
-rw-r--r-- | src/charon/encoding/message.c | 12 | ||||
-rw-r--r-- | src/charon/encoding/payloads/encryption_payload.c | 8 | ||||
-rw-r--r-- | src/charon/encoding/payloads/notify_payload.c | 25 | ||||
-rw-r--r-- | src/charon/encoding/payloads/notify_payload.h | 8 | ||||
-rw-r--r-- | src/charon/encoding/payloads/sa_payload.c | 24 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.c | 13 | ||||
-rw-r--r-- | src/charon/sa/states/ike_sa_established.c | 13 | ||||
-rw-r--r-- | src/charon/sa/states/responder_init.c | 6 | ||||
-rw-r--r-- | src/charon/testing/proposal_test.c | 33 | ||||
-rw-r--r-- | src/charon/testing/testcases.c | 2 | ||||
-rw-r--r-- | src/charon/threads/kernel_interface.c | 1 | ||||
-rwxr-xr-x | src/charon/threads/stroke_interface.c | 118 | ||||
-rw-r--r-- | src/stroke/stroke.c | 3 | ||||
-rw-r--r-- | src/stroke/stroke.h | 4 |
17 files changed, 374 insertions, 97 deletions
diff --git a/src/charon/config/connections/connection.c b/src/charon/config/connections/connection.c index 9a90f765a..a938d8b64 100644 --- a/src/charon/config/connections/connection.c +++ b/src/charon/config/connections/connection.c @@ -200,20 +200,20 @@ static diffie_hellman_group_t get_dh_group(private_connection_t *this) iterator_t *iterator; proposal_t *proposal; algorithm_t *algo; + diffie_hellman_group_t dh_group = MODP_NONE; iterator = this->proposals->create_iterator(this->proposals, TRUE); while (iterator->has_next(iterator)) { iterator->current(iterator, (void**)&proposal); - proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo); - if (algo) + if (proposal->get_algorithm(proposal, DIFFIE_HELLMAN_GROUP, &algo)) { - iterator->destroy(iterator); - return algo->algorithm; + dh_group = algo->algorithm; + break; } } iterator->destroy(iterator); - return MODP_NONE; + return dh_group; } /** diff --git a/src/charon/config/proposal.c b/src/charon/config/proposal.c index ef2ec94cb..3eb081544 100644 --- a/src/charon/config/proposal.c +++ b/src/charon/config/proposal.c @@ -27,6 +27,10 @@ #include <utils/linked_list.h> #include <utils/identification.h> #include <utils/logger.h> +#include <utils/lexparser.h> +#include <crypto/prfs/prf.h> +#include <crypto/crypters/crypter.h> +#include <crypto/signers/signer.h> /** @@ -115,8 +119,9 @@ struct private_proposal_t { */ static void add_algo(linked_list_t *list, u_int8_t algo, size_t key_size) { - algorithm_t *algo_key = malloc_thing(algorithm_t); + algorithm_t *algo_key; + algo_key = malloc_thing(algorithm_t); algo_key->algorithm = algo; algo_key->key_size = key_size; list->insert_last(list, (void*)algo_key); @@ -414,6 +419,83 @@ static void free_algo_list(linked_list_t *list) list->destroy(list); } +static status_t add_string_algo(private_proposal_t *this, chunk_t alg) +{ + if (strncmp(alg.ptr, "aes128", alg.len) == 0) + { + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); + } + else if (strncmp(alg.ptr, "aes192", alg.len) == 0) + { + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192); + } + else if (strncmp(alg.ptr, "aes256", alg.len) == 0) + { + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); + } + else if (strncmp(alg.ptr, "3des", alg.len) == 0) + { + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); + } + /* blowfish only uses some predefined key sizes yet */ + else if (strncmp(alg.ptr, "blowfish128", alg.len) == 0) + { + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128); + } + else if (strncmp(alg.ptr, "blowfish192", alg.len) == 0) + { + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192); + } + else if (strncmp(alg.ptr, "blowfish256", alg.len) == 0) + { + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256); + } + else if (strncmp(alg.ptr, "sha", alg.len) == 0 || + strncmp(alg.ptr, "sha1", alg.len) == 0) + { + /* sha means we use SHA for both, PRF and AUTH */ + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); + if (this->protocol == PROTO_IKE) + { + add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0); + } + } + else if (strncmp(alg.ptr, "md5", alg.len) == 0) + { + /* same for MD5 */ + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); + if (this->protocol == PROTO_IKE) + { + add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0); + } + } + else if (strncmp(alg.ptr, "modp1024", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0); + } + else if (strncmp(alg.ptr, "modp1536", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0); + } + else if (strncmp(alg.ptr, "modp2048", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0); + } + else if (strncmp(alg.ptr, "modp4096", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0); + } + else if (strncmp(alg.ptr, "modp8192", alg.len) == 0) + { + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0); + } + else + { + return FAILED; + } + return SUCCESS; +} + /** * Implements proposal_t.destroy. */ @@ -455,3 +537,77 @@ proposal_t *proposal_create(protocol_id_t protocol) return &this->public; } + +/* + * Describtion in header-file + */ +proposal_t *proposal_create_default(protocol_id_t protocol) +{ + private_proposal_t *this = (private_proposal_t*)proposal_create(protocol); + + switch (protocol) + { + case PROTO_IKE: + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); + add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0); + add_algorithm(this, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0); + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0); + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0); + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0); + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0); + add_algorithm(this, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0); + break; + case PROTO_ESP: + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192); + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); + add_algorithm(this, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); + break; + case PROTO_AH: + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); + add_algorithm(this, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); + break; + } + + return &this->public; +} + +/* + * Describtion in header-file + */ +proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs) +{ + private_proposal_t *this = (private_proposal_t*)proposal_create(protocol); + chunk_t string = {(void*)algs, strlen(algs)}; + chunk_t alg; + status_t status = SUCCESS; + + eat_whitespace(&string); + if (string.len < 1) + { + destroy(this); + return NULL; + } + + /* get all tokens, separated by '-' */ + while (extract_token(&alg, '-', &string)) + { + status |= add_string_algo(this, alg); + } + if (string.len) + { + status |= add_string_algo(this, string); + } + if (status != SUCCESS) + { + destroy(this); + return NULL; + } + + return &this->public; +} diff --git a/src/charon/config/proposal.h b/src/charon/config/proposal.h index 9cb8f04aa..ab58ed3bf 100644 --- a/src/charon/config/proposal.h +++ b/src/charon/config/proposal.h @@ -1,6 +1,6 @@ /** * @file proposal.h - * + * * @brief Interface of proposal_t. * */ @@ -232,12 +232,39 @@ struct proposal_t { /** * @brief Create a child proposal for AH, ESP or IKE. - * + * * @param protocol protocol, such as PROTO_ESP * @return proposal_t object - * + * * @ingroup config */ proposal_t *proposal_create(protocol_id_t protocol); +/** + * @brief Create a default proposal if nothing further specified. + * + * @param protocol protocol, such as PROTO_ESP + * @return proposal_t object + * + * @ingroup config + */ +proposal_t *proposal_create_default(protocol_id_t protocol); + +/** + * @brief Create a proposal from a string identifying the algorithms. + * + * The string is in the same form as a in the ipsec.conf file. + * E.g.: aes128-sha2_256-modp2048 + * 3des-md5 + * An additional '!' at the end of the string forces this proposal, + * without it the peer may choose another algorithm we support. + * + * @param protocol protocol, such as PROTO_ESP + * @param algs algorithms as string + * @return proposal_t object + * + * @ingroup config + */ +proposal_t *proposal_create_from_string(protocol_id_t protocol, const char *algs); + #endif /* PROPOSAL_H_ */ diff --git a/src/charon/encoding/message.c b/src/charon/encoding/message.c index 0629fb769..ece29094f 100644 --- a/src/charon/encoding/message.c +++ b/src/charon/encoding/message.c @@ -966,7 +966,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig if (payload_number != this->payloads->get_count(this->payloads)) { /* encrypted payload is not last one */ - this->logger->log(this->logger, ERROR | LEVEL1, "encrypted payload is not last payload"); + this->logger->log(this->logger, ERROR, "encrypted payload is not last payload"); iterator->destroy(iterator); return FAILED; } @@ -976,7 +976,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig status = encryption_payload->verify_signature(encryption_payload, this->packet->get_data(this->packet)); if (status != SUCCESS) { - this->logger->log(this->logger, ERROR | LEVEL1, "encryption payload signature invalid"); + this->logger->log(this->logger, ERROR, "encryption payload signature invalid"); iterator->destroy(iterator); return status; } @@ -984,7 +984,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig status = encryption_payload->decrypt(encryption_payload); if (status != SUCCESS) { - this->logger->log(this->logger, ERROR | LEVEL1, + this->logger->log(this->logger, ERROR, "encrypted payload could not be decrypted and parsed: %s", mapping_find(status_m, status)); iterator->destroy(iterator); @@ -1045,7 +1045,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig if (status != SUCCESS) { /* payload is not allowed */ - this->logger->log(this->logger, ERROR | LEVEL1, "payload type %s not allowed", + this->logger->log(this->logger, ERROR, "payload type %s not allowed", mapping_find(payload_type_m,current_payload_type)); iterator->destroy(iterator); return status; @@ -1055,7 +1055,7 @@ static status_t decrypt_payloads(private_message_t *this,crypter_t *crypter, sig if (payload_rule->encrypted != current_payload_was_encrypted) { /* payload was not encrypted, but should have been. or vice-versa */ - this->logger->log(this->logger, ERROR | LEVEL1, "payload type %s should be %s!", + this->logger->log(this->logger, ERROR, "payload type %s should be %s!", mapping_find(payload_type_m,current_payload_type), (payload_rule->encrypted) ? "encrypted" : "not encrypted"); iterator->destroy(iterator); @@ -1276,7 +1276,7 @@ message_t *message_create_notify_reply(host_t *source, host_t *destination, exch message->set_message_id(message,0); message->set_ike_sa_id(message, ike_sa_id); - payload = notify_payload_create_from_protocol_and_type(PROTO_IKE, notify_type); + payload = notify_payload_create_from_protocol_and_type(PROTO_NONE, notify_type); message->add_payload(message,(payload_t *) payload); return message; diff --git a/src/charon/encoding/payloads/encryption_payload.c b/src/charon/encoding/payloads/encryption_payload.c index 358f371e9..20d733ea1 100644 --- a/src/charon/encoding/payloads/encryption_payload.c +++ b/src/charon/encoding/payloads/encryption_payload.c @@ -385,7 +385,7 @@ static status_t decrypt(private_encryption_payload_t *this) */ if (concatenated.len < iv.len) { - this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, invalid input"); + this->logger->log(this->logger, ERROR, "could not decrypt, invalid input"); return FAILED; } @@ -397,7 +397,7 @@ static status_t decrypt(private_encryption_payload_t *this) status = this->crypter->decrypt(this->crypter, concatenated, iv, &(this->decrypted)); if (status != SUCCESS) { - this->logger->log(this->logger, ERROR|LEVEL1, "could not decrypt, decryption failed"); + this->logger->log(this->logger, ERROR, "could not decrypt, decryption failed"); return FAILED; } this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption with padding", this->decrypted); @@ -412,7 +412,7 @@ static status_t decrypt(private_encryption_payload_t *this) /* check size again */ if (padding_length > concatenated.len || this->decrypted.len < 0) { - this->logger->log(this->logger, ERROR|LEVEL1, "decryption failed, invalid padding length found. Invalid key?"); + this->logger->log(this->logger, ERROR, "decryption failed, invalid padding length found. Invalid key?"); /* decryption failed :-/ */ return FAILED; } @@ -575,7 +575,7 @@ static status_t parse(private_encryption_payload_t *this) status = current_payload->verify(current_payload); if (status != SUCCESS) { - this->logger->log(this->logger, ERROR|LEVEL1, "%s verification failed: %s", + this->logger->log(this->logger, ERROR, "%s verification failed: %s", mapping_find(payload_type_m,current_payload->get_type(current_payload)), mapping_find(status_m, status)); current_payload->destroy(current_payload); diff --git a/src/charon/encoding/payloads/notify_payload.c b/src/charon/encoding/payloads/notify_payload.c index a09e33778..575b4e5c9 100644 --- a/src/charon/encoding/payloads/notify_payload.c +++ b/src/charon/encoding/payloads/notify_payload.c @@ -175,25 +175,24 @@ static status_t verify(private_notify_payload_t *this) { switch (this->protocol_id) { + case PROTO_NONE: case PROTO_IKE: - if (this->spi.len != 8) - { - return FAILED; - } break; case PROTO_AH: case PROTO_ESP: if (this->spi.len != 4) { + this->logger->log(this->logger, ERROR, "Invalid SPI size for %s", + mapping_find(protocol_id_m, this->protocol_id)); return FAILED; } break; default: + this->logger->log(this->logger, ERROR, "Unknown protocol (%d)", this->protocol_id); return FAILED; } - - /* TODO: Check all kinds of notify */ + /* TODO: Check all kinds of notify */ if (this->notify_message_type == INVALID_KE_PAYLOAD) { /* check notification data */ @@ -316,12 +315,10 @@ static void set_notify_message_type(private_notify_payload_t *this, u_int16_t no /** * Implementation of notify_payload_t.get_spi. */ -static u_int64_t get_spi(private_notify_payload_t *this) +static u_int32_t get_spi(private_notify_payload_t *this) { switch (this->protocol_id) { - case PROTO_IKE: - return *((u_int64_t*)this->spi.ptr); case PROTO_AH: case PROTO_ESP: return *((u_int32_t*)this->spi.ptr); @@ -333,15 +330,11 @@ static u_int64_t get_spi(private_notify_payload_t *this) /** * Implementation of notify_payload_t.set_spi. */ -static void set_spi(private_notify_payload_t *this, u_int64_t spi) +static void set_spi(private_notify_payload_t *this, u_int32_t spi) { chunk_free(&this->spi); switch (this->protocol_id) { - case PROTO_IKE: - this->spi = chunk_alloc(8); - *((u_int64_t*)this->spi.ptr) = spi; - break; case PROTO_AH: case PROTO_ESP: this->spi = chunk_alloc(4); @@ -422,8 +415,8 @@ notify_payload_t *notify_payload_create() this->public.set_protocol_id = (void (*) (notify_payload_t *,u_int8_t)) set_protocol_id; this->public.get_notify_message_type = (notify_message_type_t (*) (notify_payload_t *)) get_notify_message_type; this->public.set_notify_message_type = (void (*) (notify_payload_t *,notify_message_type_t)) set_notify_message_type; - this->public.get_spi = (u_int64_t (*) (notify_payload_t *)) get_spi; - this->public.set_spi = (void (*) (notify_payload_t *,u_int64_t)) set_spi; + this->public.get_spi = (u_int32_t (*) (notify_payload_t *)) get_spi; + this->public.set_spi = (void (*) (notify_payload_t *,u_int32_t)) set_spi; this->public.get_notification_data = (chunk_t (*) (notify_payload_t *)) get_notification_data; this->public.set_notification_data = (void (*) (notify_payload_t *,chunk_t)) set_notification_data; this->public.destroy = (void (*) (notify_payload_t *)) destroy; diff --git a/src/charon/encoding/payloads/notify_payload.h b/src/charon/encoding/payloads/notify_payload.h index ef425f314..e15493691 100644 --- a/src/charon/encoding/payloads/notify_payload.h +++ b/src/charon/encoding/payloads/notify_payload.h @@ -131,19 +131,23 @@ struct notify_payload_t { /** * @brief Returns the currently set spi of this payload. + * + * This is only valid for notifys with protocol AH|ESP * * @param this calling notify_payload_t object * @return SPI value */ - u_int64_t (*get_spi) (notify_payload_t *this); + u_int32_t (*get_spi) (notify_payload_t *this); /** * @brief Sets the spi of this payload. * + * This is only valid for notifys with protocol AH|ESP + * * @param this calling notify_payload_t object * @param spi SPI value */ - void (*set_spi) (notify_payload_t *this, u_int64_t spi); + void (*set_spi) (notify_payload_t *this, u_int32_t spi); /** * @brief Returns the currently set notification data of payload. diff --git a/src/charon/encoding/payloads/sa_payload.c b/src/charon/encoding/payloads/sa_payload.c index a54e406a3..0c752b81f 100644 --- a/src/charon/encoding/payloads/sa_payload.c +++ b/src/charon/encoding/payloads/sa_payload.c @@ -26,6 +26,7 @@ #include <encoding/payloads/encodings.h> #include <utils/linked_list.h> +#include <utils/logger_manager.h> typedef struct private_sa_payload_t private_sa_payload_t; @@ -61,6 +62,11 @@ struct private_sa_payload_t { linked_list_t * proposals; /** + * Logger for error handling + */ + logger_t *logger; + + /** * @brief Computes the length of this payload. * * @param this calling private_sa_payload_t object @@ -112,7 +118,7 @@ encoding_rule_t sa_payload_encodings[] = { */ static status_t verify(private_sa_payload_t *this) { - int proposal_number = 1; + int expected_number = 1, current_number; status_t status = SUCCESS; iterator_t *iterator; bool first = TRUE; @@ -124,25 +130,28 @@ static status_t verify(private_sa_payload_t *this) { proposal_substructure_t *current_proposal; iterator->current(iterator,(void **)¤t_proposal); - if (current_proposal->get_proposal_number(current_proposal) > proposal_number) + current_number = current_proposal->get_proposal_number(current_proposal); + if (current_number > expected_number) { if (first) { - /* first number must be 1 */ + this->logger->log(this->logger, ERROR, "first proposal is not proposal #1"); status = FAILED; break; } - if (current_proposal->get_proposal_number(current_proposal) != (proposal_number + 1)) + if (current_number != (expected_number + 1)) { - /* must be only one more then previous proposal */ + this->logger->log(this->logger, ERROR, "proposal number is %d, excepted %d or %d", + current_number, expected_number, expected_number + 1); status = FAILED; break; } } - else if (current_proposal->get_proposal_number(current_proposal) < proposal_number) + else if (current_number < expected_number) { /* must not be smaller then proceeding one */ + this->logger->log(this->logger, ERROR, "proposal number smaller than that of previous proposal"); status = FAILED; break; } @@ -150,9 +159,11 @@ static status_t verify(private_sa_payload_t *this) status = current_proposal->payload_interface.verify(&(current_proposal->payload_interface)); if (status != SUCCESS) { + this->logger->log(this->logger, ERROR, "proposal substructure verification failed"); break; } first = FALSE; + expected_number = current_number; } iterator->destroy(iterator); @@ -358,6 +369,7 @@ sa_payload_t *sa_payload_create() this->critical = FALSE; this->next_payload = NO_PAYLOAD; this->payload_length = SA_PAYLOAD_HEADER_LENGTH; + this->logger = logger_manager->get_logger(logger_manager, PARSER); this->proposals = linked_list_create(); return &this->public; diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index b4a123db3..4bffae94b 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -368,8 +368,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d { this->prf->destroy(this->prf); } - proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo); - if (algo == NULL) + if (!proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo)) { this->logger->log(this->logger, ERROR|LEVEL2, "No PRF algoithm selected!?"); return FAILED; @@ -434,8 +433,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d /* SK_ai/SK_ar used for integrity protection */ - proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &algo); - if (algo == NULL) + if (!proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM, &algo)) { this->logger->log(this->logger, ERROR|LEVEL2, "No integrity algoithm selected?!"); return FAILED; @@ -472,8 +470,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d /* SK_ei/SK_er used for encryption */ - proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &algo); - if (algo == NULL) + if (!proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM, &algo)) { this->logger->log(this->logger, ERROR|LEVEL2, "No encryption algoithm selected!?"); return FAILED; @@ -510,7 +507,6 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d chunk_free(&key); /* SK_pi/SK_pr used for authentication */ - proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo); if (this->prf_auth_i != NULL) { this->prf_auth_i->destroy(this->prf_auth_i); @@ -520,6 +516,7 @@ static status_t build_transforms(private_ike_sa_t *this, proposal_t *proposal, d this->prf_auth_r->destroy(this->prf_auth_r); } + proposal->get_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, &algo); this->prf_auth_i = prf_create(algo->algorithm); this->prf_auth_r = prf_create(algo->algorithm); @@ -724,7 +721,7 @@ static void send_notify(private_ike_sa_t *this, exchange_type_t exchange_type, n this->logger->log(this->logger, CONTROL|LEVEL2, "Going to build message with notify payload"); /* set up the reply */ build_message(this, exchange_type, FALSE, &response); - payload = notify_payload_create_from_protocol_and_type(PROTO_IKE, type); + payload = notify_payload_create_from_protocol_and_type(PROTO_NONE, type); if ((data.ptr != NULL) && (data.len > 0)) { this->logger->log(this->logger, CONTROL|LEVEL2, "Add Data to notify payload"); diff --git a/src/charon/sa/states/ike_sa_established.c b/src/charon/sa/states/ike_sa_established.c index 46c181012..51ac972ba 100644 --- a/src/charon/sa/states/ike_sa_established.c +++ b/src/charon/sa/states/ike_sa_established.c @@ -133,6 +133,8 @@ static status_t build_sa_payload(private_ike_sa_established_t *this, sa_payload_ prf_plus = prf_plus_create(this->ike_sa->get_child_prf(this->ike_sa), seed); this->logger->log_chunk(this->logger, RAW|LEVEL2, "Rekey seed", seed); chunk_free(&seed); + chunk_free(&this->nonce_i); + chunk_free(&this->nonce_r); policy = this->ike_sa->get_policy(this->ike_sa); connection = this->ike_sa->get_connection(this->ike_sa); @@ -226,20 +228,19 @@ static status_t build_nonce_payload(private_ike_sa_established_t *this, nonce_pa randomizer_t *randomizer; status_t status; - this->nonce_i = nonce_request->get_nonce(nonce_request); - randomizer = this->ike_sa->get_randomizer(this->ike_sa); status = randomizer->allocate_pseudo_random_bytes(randomizer, NONCE_SIZE, &this->nonce_r); if (status != SUCCESS) { return status; } - nonce_payload = nonce_payload_create(); nonce_payload->set_nonce(nonce_payload, this->nonce_r); response->add_payload(response,(payload_t *) nonce_payload); + this->nonce_i = nonce_request->get_nonce(nonce_request); + return SUCCESS; } @@ -431,6 +432,7 @@ static status_t process_informational(private_ike_sa_established_t *this, messag * allow the clean destruction of an SA only in this state. */ this->ike_sa->set_new_state(this->ike_sa, (state_t*)delete_ike_sa_requested_create(this->ike_sa)); this->public.state_interface.destroy(&(this->public.state_interface)); + this->ike_sa->send_response(this->ike_sa, response); return DESTROY_ME; } else @@ -523,9 +525,6 @@ static status_t process_message(private_ike_sa_established_t *this, message_t *m mapping_find(exchange_type_m, message->get_exchange_type(message))); status = NOT_SUPPORTED; } - /* clean up private members */ - chunk_free(&this->nonce_i); - chunk_free(&this->nonce_r); return status; } @@ -542,6 +541,8 @@ static ike_sa_state_t get_state(private_ike_sa_established_t *this) */ static void destroy(private_ike_sa_established_t *this) { + chunk_free(&this->nonce_i); + chunk_free(&this->nonce_r); free(this); } diff --git a/src/charon/sa/states/responder_init.c b/src/charon/sa/states/responder_init.c index 3f95229fe..809dd6e29 100644 --- a/src/charon/sa/states/responder_init.c +++ b/src/charon/sa/states/responder_init.c @@ -344,8 +344,10 @@ static status_t build_sa_payload(private_responder_init_t *this,sa_payload_t *sa return DESTROY_ME; } /* get selected DH group to force policy, this is very restrictive!? */ - this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, &algo); - this->dh_group_number = algo->algorithm; + if (this->proposal->get_algorithm(this->proposal, DIFFIE_HELLMAN_GROUP, &algo)) + { + this->dh_group_number = algo->algorithm; + } this->logger->log(this->logger, CONTROL | LEVEL2, "SA Payload processed"); diff --git a/src/charon/testing/proposal_test.c b/src/charon/testing/proposal_test.c index 7adad91f5..d25573e84 100644 --- a/src/charon/testing/proposal_test.c +++ b/src/charon/testing/proposal_test.c @@ -32,15 +32,15 @@ */ void test_proposal(protected_tester_t *tester) { - proposal_t *proposal1, *proposal2, *proposal3; + proposal_t *proposal1, *proposal2, *proposal3, *proposal4; iterator_t *iterator; algorithm_t *algo; bool result; proposal1 = proposal_create(PROTO_ESP); proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); - proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 32); - proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16); + proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); + proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); proposal1->add_algorithm(proposal1, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 0); proposal1->add_algorithm(proposal1, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); proposal1->add_algorithm(proposal1, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); @@ -49,8 +49,9 @@ void test_proposal(protected_tester_t *tester) proposal2 = proposal_create(PROTO_ESP); proposal2->add_algorithm(proposal2, ENCRYPTION_ALGORITHM, ENCR_3IDEA, 0); - proposal2->add_algorithm(proposal2, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 0); + proposal2->add_algorithm(proposal2, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); proposal2->add_algorithm(proposal2, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); + proposal2->add_algorithm(proposal2, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0); /* ah and esp prop */ proposal3 = proposal1->select(proposal1, proposal2); @@ -60,13 +61,12 @@ void test_proposal(protected_tester_t *tester) result = proposal3->get_algorithm(proposal3, ENCRYPTION_ALGORITHM, &algo); tester->assert_true(tester, result, "encryption algo select"); tester->assert_true(tester, algo->algorithm == ENCR_AES_CBC, "encryption algo"); - tester->assert_true(tester, algo->key_size == 16, "encryption keylen"); + tester->assert_true(tester, algo->key_size == 128, "encryption keylen"); result = proposal3->get_algorithm(proposal3, INTEGRITY_ALGORITHM, &algo); tester->assert_true(tester, result, "integrity algo select"); tester->assert_true(tester, algo->algorithm == AUTH_HMAC_MD5_96, "integrity algo"); - tester->assert_true(tester, algo->key_size == 16, "integrity keylen"); iterator = proposal3->create_algorithm_iterator(proposal3, INTEGRITY_ALGORITHM); tester->assert_false(tester, iterator == NULL, "integrity algo select"); @@ -74,7 +74,6 @@ void test_proposal(protected_tester_t *tester) { iterator->current(iterator, (void**)&algo); tester->assert_true(tester, algo->algorithm == AUTH_HMAC_MD5_96, "integrity algo"); - tester->assert_true(tester, algo->key_size == 16, "integrity keylen"); } iterator->destroy(iterator); proposal3->destroy(proposal3); @@ -82,5 +81,25 @@ void test_proposal(protected_tester_t *tester) proposal1->destroy(proposal1); proposal2->destroy(proposal2); + + /* from string tests */ + + proposal1 = proposal_create_from_string(PROTO_ESP, "3des-md5!"); + proposal2 = proposal_create_from_string(PROTO_ESP, "3des-md5-modp1024!"); + proposal3 = proposal_create_from_string(PROTO_ESP, "aes256-sha1"); + + proposal4 = proposal1->select(proposal1, proposal2); + tester->assert_true(tester, proposal4 == NULL, "from string 1"); + + proposal4 = proposal1->select(proposal1, proposal3); + tester->assert_true(tester, proposal4 != NULL, "from string 2"); + + result = proposal4->get_algorithm(proposal4, ENCRYPTION_ALGORITHM, &algo); + tester->assert_true(tester, result, "from string 3"); + tester->assert_true(tester, algo->algorithm == ENCR_3DES, "from string 4"); + result = proposal4->get_algorithm(proposal4, INTEGRITY_ALGORITHM, &algo); + tester->assert_true(tester, result, "from string 5"); + tester->assert_true(tester, algo->algorithm == AUTH_HMAC_MD5_96, "from string 6"); + return; } diff --git a/src/charon/testing/testcases.c b/src/charon/testing/testcases.c index 2c8c04a68..c4a4ad986 100644 --- a/src/charon/testing/testcases.c +++ b/src/charon/testing/testcases.c @@ -252,7 +252,7 @@ int main() tester_t *tester = tester_create(test_output, FALSE); //tester->perform_tests(tester,all_tests); - tester->perform_test(tester,&kernel_interface_test); + tester->perform_test(tester,&proposal_test); tester->destroy(tester); diff --git a/src/charon/threads/kernel_interface.c b/src/charon/threads/kernel_interface.c index 617e324bb..64160738a 100644 --- a/src/charon/threads/kernel_interface.c +++ b/src/charon/threads/kernel_interface.c @@ -302,6 +302,7 @@ static status_t get_spi(private_kernel_interface_t *this, else { *spi = response->sa.id.spi; + this->logger->log(this->logger, CONTROL|LEVEL1, "SPI is 0x%x", *spi); } free(response); diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c index a98d4761a..67ed97cea 100755 --- a/src/charon/threads/stroke_interface.c +++ b/src/charon/threads/stroke_interface.c @@ -179,7 +179,9 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) pop_string(msg, &msg->add_conn.other.cert); pop_string(msg, &msg->add_conn.me.ca); pop_string(msg, &msg->add_conn.other.ca); - + pop_string(msg, &msg->add_conn.algorithms.ike); + pop_string(msg, &msg->add_conn.algorithms.esp); + this->logger->log(this->logger, CONTROL, "received stroke: add connection \"%s\"", msg->add_conn.name); my_host = msg->add_conn.me.address? @@ -343,18 +345,91 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) connection = connection_create(msg->add_conn.name, msg->add_conn.ikev2, my_host, other_host, RSA_DIGITAL_SIGNATURE); - proposal = proposal_create(PROTO_IKE); - proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); - proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); - proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); - proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0); - proposal->add_algorithm(proposal, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0); - proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0); - proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0); - proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0); - proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0); - proposal->add_algorithm(proposal, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0); - connection->add_proposal(connection, proposal); + if (msg->add_conn.algorithms.ike) + { + char *proposal_string; + char *strict = msg->add_conn.algorithms.ike + strlen(msg->add_conn.algorithms.ike) - 1; + if (*strict == '!') + { + *strict = '\0'; + } + else + { + strict = NULL; + } + while ((proposal_string = strsep(&msg->add_conn.algorithms.ike, ","))) + { + proposal = proposal_create_from_string(PROTO_IKE, proposal_string); + if (proposal == NULL) + { + this->logger->log(this->logger, ERROR, "invalid IKE proposal string: %s", msg->add_conn.algorithms.esp); + my_id->destroy(my_id); + other_id->destroy(other_id); + my_ts->destroy(my_ts); + other_ts->destroy(other_ts); + my_ca->destroy(my_ca); + other_ca->destroy(other_ca); + connection->destroy(connection); + return; + } + connection->add_proposal(connection, proposal); + } + if (!strict) + { + proposal = proposal_create_default(PROTO_IKE); + connection->add_proposal(connection, proposal); + } + } + else + { + proposal = proposal_create_default(PROTO_IKE); + connection->add_proposal(connection, proposal); + } + + policy = policy_create(msg->add_conn.name, my_id, other_id, + msg->add_conn.rekey.ipsec_lifetime, + msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin, + msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100); + policy->add_my_traffic_selector(policy, my_ts); + policy->add_other_traffic_selector(policy, other_ts); + policy->add_authorities(policy, my_ca, other_ca); + + if (msg->add_conn.algorithms.esp) + { + char *proposal_string; + char *strict = msg->add_conn.algorithms.esp + strlen(msg->add_conn.algorithms.esp) - 1; + if (*strict == '!') + { + *strict = '\0'; + } + else + { + strict = NULL; + } + + while ((proposal_string = strsep(&msg->add_conn.algorithms.esp, ","))) + { + proposal = proposal_create_from_string(PROTO_ESP, proposal_string); + if (proposal == NULL) + { + this->logger->log(this->logger, ERROR, "invalid ESP proposal string: %s", msg->add_conn.algorithms.esp); + policy->destroy(policy); + connection->destroy(connection); + return; + } + policy->add_proposal(policy, proposal); + } + if (!strict) + { + proposal = proposal_create_default(PROTO_ESP); + policy->add_proposal(policy, proposal); + } + } + else + { + proposal = proposal_create_default(PROTO_ESP); + policy->add_proposal(policy, proposal); + } /* add to global connection list */ charon->connections->add_connection(charon->connections, connection); @@ -364,23 +439,6 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg) my_id->get_string(my_id), other_host->get_address(other_host), other_id->get_string(other_id)); - - policy = policy_create(msg->add_conn.name, my_id, other_id, - msg->add_conn.rekey.ipsec_lifetime, - msg->add_conn.rekey.ipsec_lifetime - msg->add_conn.rekey.margin, - msg->add_conn.rekey.margin * msg->add_conn.rekey.fuzz / 100); - proposal = proposal_create(PROTO_ESP); - proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128); - proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256); - proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, ENCR_3DES, 0); - proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256); - proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0); - proposal->add_algorithm(proposal, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0); - policy->add_proposal(policy, proposal); - policy->add_my_traffic_selector(policy, my_ts); - policy->add_other_traffic_selector(policy, other_ts); - policy->add_authorities(policy, my_ca, other_ca); - /* add to global policy list */ charon->policies->add_policy(charon->policies, policy); } diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c index b8b0cc093..7d9e67403 100644 --- a/src/stroke/stroke.c +++ b/src/stroke/stroke.c @@ -113,6 +113,9 @@ static int add_connection(char *name, msg.add_conn.rekey.tries = 0; msg.add_conn.rekey.fuzz = 0; + msg.add_conn.algorithms.ike = NULL; + msg.add_conn.algorithms.esp = NULL; + msg.add_conn.me.id = push_string(&msg, my_id); msg.add_conn.me.address = push_string(&msg, my_addr); msg.add_conn.me.subnet = push_string(&msg, my_net); diff --git a/src/stroke/stroke.h b/src/stroke/stroke.h index 0544ca8bf..64a538bbd 100644 --- a/src/stroke/stroke.h +++ b/src/stroke/stroke.h @@ -96,6 +96,10 @@ struct stroke_msg_t { char *name; bool ikev2; struct { + char *ike; + char *esp; + } algorithms; + struct { time_t ipsec_lifetime; time_t ike_lifetime; time_t margin; |