From 526b5afb4510163372f7981e57d69fad3ea53906 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 15 Nov 2011 13:53:56 +0100 Subject: Extended IKE header for IKEv1 support --- src/libcharon/encoding/message.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 2b5399294..fa724e4b1 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1120,9 +1120,8 @@ METHOD(message_t, generate, status_t, DBG2(DBG_ENC, "not encrypting payloads"); } - ike_header = ike_header_create(); - ike_header->set_maj_version(ike_header, this->major_version); - ike_header->set_min_version(ike_header, this->minor_version); + ike_header = ike_header_create_version(this->major_version, + this->minor_version); ike_header->set_exchange_type(ike_header, this->exchange_type); ike_header->set_message_id(ike_header, this->message_id); ike_header->set_response_flag(ike_header, !this->is_request); @@ -1567,8 +1566,8 @@ message_t *message_create_from_packet(packet_t *packet) .get_packet_data = _get_packet_data, .destroy = _destroy, }, - .major_version = IKE_MAJOR_VERSION, - .minor_version = IKE_MINOR_VERSION, + .major_version = IKEV2_MAJOR_VERSION, + .minor_version = IKEV2_MINOR_VERSION, .exchange_type = EXCHANGE_TYPE_UNDEFINED, .is_request = TRUE, .first_payload = NO_PAYLOAD, -- cgit v1.2.3 From 6ba70ba8dd2ffcd28fc1aeaf106f8561ef947634 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 15 Nov 2011 16:13:50 +0100 Subject: Message rules for IKEv1 ID_PROT exchange added. These rules are quite broad and cover main mode with at least PSK and signature based authentication. --- src/libcharon/encoding/message.c | 77 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index fa724e4b1..eab3427a1 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -414,6 +414,72 @@ static payload_order_t me_connect_r_order[] = { }; #endif /* ME */ +#ifdef USE_IKEV1 +/** + * Message rule for ID_PROT from initiator. + */ +static payload_rule_t id_prot_i_rules[] = { +/* payload type min max encr suff */ + {NOTIFICATION_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, + {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE}, + {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, + {NONCE_V1, 0, 1, FALSE, FALSE}, + {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, + {ID_V1, 0, 1, TRUE, FALSE}, + {CERTIFICATE_V1, 0, 1, TRUE, FALSE}, + {SIGNATURE_V1, 0, 1, TRUE, FALSE}, + {HASH_V1, 0, 1, TRUE, FALSE}, +}; + +/** + * payload order for ID_PROT from initiator. + */ +static payload_order_t id_prot_i_order[] = { +/* payload type notify type */ + {SECURITY_ASSOCIATION_V1, 0}, + {KEY_EXCHANGE_V1, 0}, + {NONCE_V1, 0}, + {ID_V1, 0}, + {CERTIFICATE_V1, 0}, + {SIGNATURE_V1, 0}, + {HASH_V1, 0}, + {NOTIFICATION_V1, 0}, + {VENDOR_ID_V1, 0}, +}; + +/** + * Message rule for ID_PROT from responder. + */ +static payload_rule_t id_prot_r_rules[] = { +/* payload type min max encr suff */ + {NOTIFICATION_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, + {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE}, + {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, + {NONCE_V1, 0, 1, FALSE, FALSE}, + {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, + {ID_V1, 0, 1, TRUE, FALSE}, + {CERTIFICATE_V1, 0, 1, TRUE, FALSE}, + {SIGNATURE_V1, 0, 1, TRUE, FALSE}, + {HASH_V1, 0, 1, TRUE, FALSE}, +}; + +/** + * payload order for ID_PROT from responder. + */ +static payload_order_t id_prot_r_order[] = { +/* payload type notify type */ + {SECURITY_ASSOCIATION_V1, 0}, + {KEY_EXCHANGE_V1, 0}, + {NONCE_V1, 0}, + {ID_V1, 0}, + {CERTIFICATE_V1, 0}, + {SIGNATURE_V1, 0}, + {HASH_V1, 0}, + {NOTIFICATION_V1, 0}, + {VENDOR_ID_V1, 0}, +}; +#endif /* USE_IKEV1 */ + /** * Message rules, defines allowed payloads. */ @@ -460,6 +526,17 @@ static message_rule_t message_rules[] = { countof(me_connect_r_order), me_connect_r_order, }, #endif /* ME */ +#ifdef USE_IKEV1 + {ID_PROT, TRUE, FALSE, + countof(id_prot_i_rules), id_prot_i_rules, + countof(id_prot_i_order), id_prot_i_order, + }, + {ID_PROT, FALSE, FALSE, + countof(id_prot_r_rules), id_prot_r_rules, + countof(id_prot_r_order), id_prot_r_order, + }, + /* TODO-IKEv1: define rules for other exchanges */ +#endif /* USE_IKEV1 */ }; -- cgit v1.2.3 From 130c9a54c2c9c5586d685bf98b3bf004f7465d8f Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 15 Nov 2011 18:21:28 +0100 Subject: Message rules for IKEv1 AGGRESSIVE exchange added. These are basically the same as for ID_PROT but no payloads are expected to be encrypted (at least if using PSK or signatures for authentication). --- src/libcharon/encoding/message.c | 72 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index eab3427a1..5386d4984 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -478,6 +478,70 @@ static payload_order_t id_prot_r_order[] = { {NOTIFICATION_V1, 0}, {VENDOR_ID_V1, 0}, }; + +/** + * Message rule for AGGRESSIVE from initiator. + */ +static payload_rule_t aggressive_i_rules[] = { +/* payload type min max encr suff */ + {NOTIFICATION_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, + {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE}, + {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, + {NONCE_V1, 0, 1, FALSE, FALSE}, + {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, + {ID_V1, 0, 1, FALSE, FALSE}, + {CERTIFICATE_V1, 0, 1, FALSE, FALSE}, + {SIGNATURE_V1, 0, 1, FALSE, FALSE}, + {HASH_V1, 0, 1, FALSE, FALSE}, +}; + +/** + * payload order for AGGRESSIVE from initiator. + */ +static payload_order_t aggressive_i_order[] = { +/* payload type notify type */ + {SECURITY_ASSOCIATION_V1, 0}, + {KEY_EXCHANGE_V1, 0}, + {NONCE_V1, 0}, + {ID_V1, 0}, + {CERTIFICATE_V1, 0}, + {SIGNATURE_V1, 0}, + {HASH_V1, 0}, + {NOTIFICATION_V1, 0}, + {VENDOR_ID_V1, 0}, +}; + +/** + * Message rule for AGGRESSIVE from responder. + */ +static payload_rule_t aggressive_r_rules[] = { +/* payload type min max encr suff */ + {NOTIFICATION_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, + {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE}, + {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, + {NONCE_V1, 0, 1, FALSE, FALSE}, + {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, + {ID_V1, 0, 1, FALSE, FALSE}, + {CERTIFICATE_V1, 0, 1, FALSE, FALSE}, + {SIGNATURE_V1, 0, 1, FALSE, FALSE}, + {HASH_V1, 0, 1, FALSE, FALSE}, +}; + +/** + * payload order for AGGRESSIVE from responder. + */ +static payload_order_t aggressive_r_order[] = { +/* payload type notify type */ + {SECURITY_ASSOCIATION_V1, 0}, + {KEY_EXCHANGE_V1, 0}, + {NONCE_V1, 0}, + {ID_V1, 0}, + {CERTIFICATE_V1, 0}, + {SIGNATURE_V1, 0}, + {HASH_V1, 0}, + {NOTIFICATION_V1, 0}, + {VENDOR_ID_V1, 0}, +}; #endif /* USE_IKEV1 */ /** @@ -535,6 +599,14 @@ static message_rule_t message_rules[] = { countof(id_prot_r_rules), id_prot_r_rules, countof(id_prot_r_order), id_prot_r_order, }, + {AGGRESSIVE, TRUE, FALSE, + countof(aggressive_i_rules), aggressive_i_rules, + countof(aggressive_i_order), aggressive_i_order, + }, + {AGGRESSIVE, FALSE, FALSE, + countof(aggressive_r_rules), aggressive_r_rules, + countof(aggressive_r_order), aggressive_r_order, + }, /* TODO-IKEv1: define rules for other exchanges */ #endif /* USE_IKEV1 */ }; -- cgit v1.2.3 From 8f3aea2f774c5647c6cb7e4da664c6323f5cc669 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 15 Nov 2011 18:23:15 +0100 Subject: Message rules for IKEv1 INFORMATIONAL exchange added. Since INFORMATIONAL "exchanges" are actually unidirectionally sent message we don't have any responder rules. --- src/libcharon/encoding/message.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 5386d4984..823a97f0f 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -542,6 +542,26 @@ static payload_order_t aggressive_r_order[] = { {NOTIFICATION_V1, 0}, {VENDOR_ID_V1, 0}, }; + +/** + * Message rule for INFORMATIONAL_V1 from initiator. + */ +static payload_rule_t informational_i_rules_v1[] = { +/* payload type min max encr suff */ + {NOTIFICATION_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, + {DELETE_V1, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE}, + {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, +}; + +/** + * payload order for INFORMATIONAL_V1 from initiator. + */ +static payload_order_t informational_i_order_v1[] = { +/* payload type notify type */ + {NOTIFICATION_V1, 0}, + {DELETE_V1, 0}, + {VENDOR_ID_V1, 0}, +}; #endif /* USE_IKEV1 */ /** @@ -607,6 +627,10 @@ static message_rule_t message_rules[] = { countof(aggressive_r_rules), aggressive_r_rules, countof(aggressive_r_order), aggressive_r_order, }, + {INFORMATIONAL_V1, TRUE, TRUE, + countof(informational_i_rules_v1), informational_i_rules_v1, + countof(informational_i_order_v1), informational_i_order_v1, + }, /* TODO-IKEv1: define rules for other exchanges */ #endif /* USE_IKEV1 */ }; -- cgit v1.2.3 From 8a2d079d785e069891dcae41e7b1aae51f50c9ae Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 16 Nov 2011 10:31:53 +0100 Subject: Certificate request payloads can be sent in pretty much any IKEv1 message. --- src/libcharon/encoding/message.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 823a97f0f..58b7df505 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2007 Tobias Brunner + * Copyright (C) 2006-2011 Tobias Brunner * Copyright (C) 2005-2010 Martin Willi * Copyright (C) 2010 revosec AG * Copyright (C) 2006 Daniel Roethlisberger @@ -35,25 +35,30 @@ #include /** - * Max number of notify payloads per IKEv2 Message + * Max number of notify payloads per IKEv2 message */ #define MAX_NOTIFY_PAYLOADS 20 /** - * Max number of delete payloads per IKEv2 Message + * Max number of delete payloads per IKEv2 message */ #define MAX_DELETE_PAYLOADS 20 /** - * Max number of certificate payloads per IKEv2 Message + * Max number of certificate payloads per IKEv2 message */ #define MAX_CERT_PAYLOADS 8 /** - * Max number of Vendor ID payloads per IKEv2 Message + * Max number of vendor ID payloads per IKEv2 message */ #define MAX_VID_PAYLOADS 20 +/** + * Max number of certificate request payloads per IKEv1 message + */ +#define MAX_CERTREQ_PAYLOADS 5 + /** * A payload rule defines the rules for a payload * in a specific message rule. It defines if and how @@ -425,6 +430,7 @@ static payload_rule_t id_prot_i_rules[] = { {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, {NONCE_V1, 0, 1, FALSE, FALSE}, {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, + {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, {ID_V1, 0, 1, TRUE, FALSE}, {CERTIFICATE_V1, 0, 1, TRUE, FALSE}, {SIGNATURE_V1, 0, 1, TRUE, FALSE}, @@ -443,6 +449,7 @@ static payload_order_t id_prot_i_order[] = { {CERTIFICATE_V1, 0}, {SIGNATURE_V1, 0}, {HASH_V1, 0}, + {CERTIFICATE_REQUEST_V1, 0}, {NOTIFICATION_V1, 0}, {VENDOR_ID_V1, 0}, }; @@ -457,6 +464,7 @@ static payload_rule_t id_prot_r_rules[] = { {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, {NONCE_V1, 0, 1, FALSE, FALSE}, {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, + {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, {ID_V1, 0, 1, TRUE, FALSE}, {CERTIFICATE_V1, 0, 1, TRUE, FALSE}, {SIGNATURE_V1, 0, 1, TRUE, FALSE}, @@ -475,6 +483,7 @@ static payload_order_t id_prot_r_order[] = { {CERTIFICATE_V1, 0}, {SIGNATURE_V1, 0}, {HASH_V1, 0}, + {CERTIFICATE_REQUEST_V1, 0}, {NOTIFICATION_V1, 0}, {VENDOR_ID_V1, 0}, }; @@ -489,6 +498,7 @@ static payload_rule_t aggressive_i_rules[] = { {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, {NONCE_V1, 0, 1, FALSE, FALSE}, {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, + {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, {ID_V1, 0, 1, FALSE, FALSE}, {CERTIFICATE_V1, 0, 1, FALSE, FALSE}, {SIGNATURE_V1, 0, 1, FALSE, FALSE}, @@ -507,6 +517,7 @@ static payload_order_t aggressive_i_order[] = { {CERTIFICATE_V1, 0}, {SIGNATURE_V1, 0}, {HASH_V1, 0}, + {CERTIFICATE_REQUEST_V1, 0}, {NOTIFICATION_V1, 0}, {VENDOR_ID_V1, 0}, }; @@ -521,6 +532,7 @@ static payload_rule_t aggressive_r_rules[] = { {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, {NONCE_V1, 0, 1, FALSE, FALSE}, {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, + {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, {ID_V1, 0, 1, FALSE, FALSE}, {CERTIFICATE_V1, 0, 1, FALSE, FALSE}, {SIGNATURE_V1, 0, 1, FALSE, FALSE}, @@ -539,6 +551,7 @@ static payload_order_t aggressive_r_order[] = { {CERTIFICATE_V1, 0}, {SIGNATURE_V1, 0}, {HASH_V1, 0}, + {CERTIFICATE_REQUEST_V1, 0}, {NOTIFICATION_V1, 0}, {VENDOR_ID_V1, 0}, }; -- cgit v1.2.3 From 4ed52db2bbe4d884e5e0ed507b0d9c19f7b4343e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 16 Nov 2011 12:06:55 +0100 Subject: Allow creation of message_t objects for IKEv1 packets. --- src/libcharon/encoding/message.c | 52 ++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 20 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 58b7df505..71ff4b068 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -686,6 +686,11 @@ struct private_message_t { */ bool is_request; + /** + * The message is encrypted (IKEv1) + */ + bool is_encrypted; + /** * Higher version supported? */ @@ -694,7 +699,7 @@ struct private_message_t { /** * Reserved bits in IKE header */ - bool reserved[5]; + bool reserved[2]; /** * Sorting of message disabled? @@ -1422,13 +1427,15 @@ METHOD(message_t, parse_header, status_t, } DESTROY_IF(this->ike_sa_id); - this->ike_sa_id = ike_sa_id_create(ike_header->get_initiator_spi(ike_header), + this->ike_sa_id = ike_sa_id_create( + ike_header->get_initiator_spi(ike_header), ike_header->get_responder_spi(ike_header), ike_header->get_initiator_flag(ike_header)); this->exchange_type = ike_header->get_exchange_type(ike_header); this->message_id = ike_header->get_message_id(ike_header); this->is_request = !ike_header->get_response_flag(ike_header); + this->is_encrypted = ike_header->get_encryption_flag(ike_header); this->major_version = ike_header->get_maj_version(ike_header); this->minor_version = ike_header->get_min_version(ike_header); this->first_payload = ike_header->payload_interface.get_next_type( @@ -1442,19 +1449,12 @@ METHOD(message_t, parse_header, status_t, this->reserved[i] = *reserved; } } - DBG2(DBG_ENC, "parsed a %N %s", exchange_type_names, this->exchange_type, - this->is_request ? "request" : "response"); - ike_header->destroy(ike_header); - this->rule = get_message_rule(this); - if (!this->rule) - { - DBG1(DBG_ENC, "no message rules specified for a %N %s", - exchange_type_names, this->exchange_type, - this->is_request ? "request" : "response"); - } - return status; + DBG2(DBG_ENC, "parsed a %N %s header", exchange_type_names, + this->exchange_type, this->major_version == IKEV1_MAJOR_VERSION ? + "message" : (this->is_request ? "request" : "response")); + return SUCCESS; } /** @@ -1640,6 +1640,15 @@ METHOD(message_t, parse_body, status_t, DBG2(DBG_ENC, "parsing body of message, first payload is %N", payload_type_names, type); + this->rule = get_message_rule(this); + if (!this->rule) + { + DBG1(DBG_ENC, "no message rules specified for a %N %s", + exchange_type_names, this->exchange_type, + this->is_request ? "request" : "response"); + return PARSE_ERROR; + } + while (type != NO_PAYLOAD) { DBG2(DBG_ENC, "starting parsing a %N payload", @@ -1707,7 +1716,7 @@ METHOD(message_t, destroy, void, } /* - * Described in Header-File + * Described in header. */ message_t *message_create_from_packet(packet_t *packet) { @@ -1752,8 +1761,6 @@ message_t *message_create_from_packet(packet_t *packet) .get_packet_data = _get_packet_data, .destroy = _destroy, }, - .major_version = IKEV2_MAJOR_VERSION, - .minor_version = IKEV2_MINOR_VERSION, .exchange_type = EXCHANGE_TYPE_UNDEFINED, .is_request = TRUE, .first_payload = NO_PAYLOAD, @@ -1762,14 +1769,19 @@ message_t *message_create_from_packet(packet_t *packet) .parser = parser_create(packet->get_data(packet)), ); - return (&this->public); + return &this->public; } /* - * Described in Header. + * Described in header. */ -message_t *message_create() +message_t *message_create(int major, int minor) { - return message_create_from_packet(packet_create()); + message_t *this = message_create_from_packet(packet_create()); + + this->set_major_version(this, major); + this->set_minor_version(this, minor); + + return this; } -- cgit v1.2.3 From 7f56cf1a650254d0aee249b4fc87cbea78ae6073 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 16 Nov 2011 14:23:50 +0100 Subject: Message parsing slightly refactored, allows parsing of unencrypted IKEv1 messages. --- src/libcharon/encoding/message.c | 92 +++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 40 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 71ff4b068..1dad23bc2 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1482,6 +1482,53 @@ static bool is_connectivity_check(private_message_t *this, payload_t *payload) return FALSE; } +/** + * Parses and verifies the unencrypted payloads contained in the message + */ +static status_t parse_payloads(private_message_t *this) +{ + payload_type_t type = this->first_payload; + + while (type != NO_PAYLOAD) + { + DBG2(DBG_ENC, "starting parsing a %N payload", + payload_type_names, type); + + status = this->parser->parse_payload(this->parser, type, &payload); + if (status != SUCCESS) + { + DBG1(DBG_ENC, "payload type %N could not be parsed", + payload_type_names, type); + return PARSE_ERROR; + } + + DBG2(DBG_ENC, "verifying payload of type %N", payload_type_names, type); + status = payload->verify(payload); + if (status != SUCCESS) + { + DBG1(DBG_ENC, "%N payload verification failed", + payload_type_names, type); + payload->destroy(payload); + return VERIFY_ERROR; + } + + DBG2(DBG_ENC, "%N payload verified. Adding to payload list", + payload_type_names, type); + this->payloads->insert_last(this->payloads, payload); + + /* an encryption payload is the last one, so STOP here. decryption is + * done later */ + if (type == ENCRYPTED) + { + DBG2(DBG_ENC, "%N payload found. Stop parsing", + payload_type_names, type); + break; + } + type = payload->get_next_type(payload); + } + return SUCCESS; +} + /** * Decrypt payload from the encryption payload */ @@ -1632,13 +1679,10 @@ METHOD(message_t, parse_body, status_t, { status_t status = SUCCESS; payload_t *payload; - payload_type_t type; char str[BUF_LEN]; - type = this->first_payload; - DBG2(DBG_ENC, "parsing body of message, first payload is %N", - payload_type_names, type); + payload_type_names, this->first_payload); this->rule = get_message_rule(this); if (!this->rule) @@ -1649,42 +1693,10 @@ METHOD(message_t, parse_body, status_t, return PARSE_ERROR; } - while (type != NO_PAYLOAD) - { - DBG2(DBG_ENC, "starting parsing a %N payload", - payload_type_names, type); - - status = this->parser->parse_payload(this->parser, type, &payload); - if (status != SUCCESS) - { - DBG1(DBG_ENC, "payload type %N could not be parsed", - payload_type_names, type); - return this->exchange_type == IKE_SA_INIT ? PARSE_ERROR : FAILED; - } - - DBG2(DBG_ENC, "verifying payload of type %N", payload_type_names, type); - status = payload->verify(payload); - if (status != SUCCESS) - { - DBG1(DBG_ENC, "%N payload verification failed", - payload_type_names, type); - payload->destroy(payload); - return this->exchange_type == IKE_SA_INIT ? VERIFY_ERROR : FAILED; - } - - DBG2(DBG_ENC, "%N payload verified. Adding to payload list", - payload_type_names, type); - this->payloads->insert_last(this->payloads, payload); - - /* an encryption payload is the last one, so STOP here. decryption is - * done later */ - if (type == ENCRYPTED) - { - DBG2(DBG_ENC, "%N payload found. Stop parsing", - payload_type_names, type); - break; - } - type = payload->get_next_type(payload); + status = parse_payloads(this); + if (status != SUCCESS) + { /* error is already logged */ + return status; } status = decrypt_payloads(this, aead); -- cgit v1.2.3 From 354ac9579f92d69a54b70b2010c7a5d35893eebc Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 16 Nov 2011 15:05:08 +0100 Subject: Compile error fixed. --- src/libcharon/encoding/message.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 1dad23bc2..91d7f3df9 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1488,6 +1488,8 @@ static bool is_connectivity_check(private_message_t *this, payload_t *payload) static status_t parse_payloads(private_message_t *this) { payload_type_t type = this->first_payload; + payload_t *payload; + status_t status; while (type != NO_PAYLOAD) { @@ -1678,7 +1680,6 @@ METHOD(message_t, parse_body, status_t, private_message_t *this, aead_t *aead) { status_t status = SUCCESS; - payload_t *payload; char str[BUF_LEN]; DBG2(DBG_ENC, "parsing body of message, first payload is %N", -- cgit v1.2.3 From bce8d3be1182f249659f2c01ac7feca58de533f4 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 16 Nov 2011 18:23:00 +0100 Subject: Don't set IKEv2 only header flags when using IKEv1 --- src/libcharon/encoding/message.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 91d7f3df9..6640b7696 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1315,10 +1315,13 @@ METHOD(message_t, generate, status_t, this->minor_version); ike_header->set_exchange_type(ike_header, this->exchange_type); ike_header->set_message_id(ike_header, this->message_id); - ike_header->set_response_flag(ike_header, !this->is_request); - ike_header->set_version_flag(ike_header, this->version_flag); - ike_header->set_initiator_flag(ike_header, + if (this->major_version == IKEV2_MAJOR_VERSION) + { + ike_header->set_response_flag(ike_header, !this->is_request); + ike_header->set_version_flag(ike_header, this->version_flag); + ike_header->set_initiator_flag(ike_header, this->ike_sa_id->is_initiator(this->ike_sa_id)); + } ike_header->set_initiator_spi(ike_header, this->ike_sa_id->get_initiator_spi(this->ike_sa_id)); ike_header->set_responder_spi(ike_header, -- cgit v1.2.3 From 04ee2b7fed91b4430ba4870a2f1b98ee3e228f50 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 17 Nov 2011 18:01:41 +0100 Subject: Added IKEv1 support to notify payload --- src/libcharon/encoding/message.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 6640b7696..0789da4b7 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -425,7 +425,7 @@ static payload_order_t me_connect_r_order[] = { */ static payload_rule_t id_prot_i_rules[] = { /* payload type min max encr suff */ - {NOTIFICATION_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, + {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE}, {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, {NONCE_V1, 0, 1, FALSE, FALSE}, @@ -450,7 +450,7 @@ static payload_order_t id_prot_i_order[] = { {SIGNATURE_V1, 0}, {HASH_V1, 0}, {CERTIFICATE_REQUEST_V1, 0}, - {NOTIFICATION_V1, 0}, + {NOTIFY_V1, 0}, {VENDOR_ID_V1, 0}, }; @@ -459,7 +459,7 @@ static payload_order_t id_prot_i_order[] = { */ static payload_rule_t id_prot_r_rules[] = { /* payload type min max encr suff */ - {NOTIFICATION_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, + {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE}, {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, {NONCE_V1, 0, 1, FALSE, FALSE}, @@ -484,7 +484,7 @@ static payload_order_t id_prot_r_order[] = { {SIGNATURE_V1, 0}, {HASH_V1, 0}, {CERTIFICATE_REQUEST_V1, 0}, - {NOTIFICATION_V1, 0}, + {NOTIFY_V1, 0}, {VENDOR_ID_V1, 0}, }; @@ -493,7 +493,7 @@ static payload_order_t id_prot_r_order[] = { */ static payload_rule_t aggressive_i_rules[] = { /* payload type min max encr suff */ - {NOTIFICATION_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, + {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE}, {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, {NONCE_V1, 0, 1, FALSE, FALSE}, @@ -518,7 +518,7 @@ static payload_order_t aggressive_i_order[] = { {SIGNATURE_V1, 0}, {HASH_V1, 0}, {CERTIFICATE_REQUEST_V1, 0}, - {NOTIFICATION_V1, 0}, + {NOTIFY_V1, 0}, {VENDOR_ID_V1, 0}, }; @@ -527,7 +527,7 @@ static payload_order_t aggressive_i_order[] = { */ static payload_rule_t aggressive_r_rules[] = { /* payload type min max encr suff */ - {NOTIFICATION_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, + {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, {SECURITY_ASSOCIATION_V1, 0, 1, FALSE, FALSE}, {KEY_EXCHANGE_V1, 0, 1, FALSE, FALSE}, {NONCE_V1, 0, 1, FALSE, FALSE}, @@ -552,7 +552,7 @@ static payload_order_t aggressive_r_order[] = { {SIGNATURE_V1, 0}, {HASH_V1, 0}, {CERTIFICATE_REQUEST_V1, 0}, - {NOTIFICATION_V1, 0}, + {NOTIFY_V1, 0}, {VENDOR_ID_V1, 0}, }; @@ -561,7 +561,7 @@ static payload_order_t aggressive_r_order[] = { */ static payload_rule_t informational_i_rules_v1[] = { /* payload type min max encr suff */ - {NOTIFICATION_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, + {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, {DELETE_V1, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE}, {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, }; @@ -571,7 +571,7 @@ static payload_rule_t informational_i_rules_v1[] = { */ static payload_order_t informational_i_order_v1[] = { /* payload type notify type */ - {NOTIFICATION_V1, 0}, + {NOTIFY_V1, 0}, {DELETE_V1, 0}, {VENDOR_ID_V1, 0}, }; @@ -930,7 +930,14 @@ METHOD(message_t, add_notify, void, payload->destroy(payload); } } - notify = notify_payload_create(); + if (this->major_version == IKEV2_MAJOR_VERSION) + { + notify = notify_payload_create(NOTIFY); + } + else + { + notify = notify_payload_create(NOTIFY_V1); + } notify->set_notify_type(notify, type); notify->set_notification_data(notify, data); add_payload(this, (payload_t*)notify); -- cgit v1.2.3 From c311d22d0f62b68bf0e69c110d94b569788c0fd3 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Fri, 18 Nov 2011 17:49:53 +0100 Subject: Don't clone chunk in message.get_packet_data --- src/libcharon/encoding/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 0789da4b7..afa9b1956 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1404,7 +1404,7 @@ METHOD(message_t, get_packet_data, chunk_t, { return chunk_empty; } - return chunk_clone(this->packet->get_data(this->packet)); + return this->packet->get_data(this->packet); } METHOD(message_t, parse_header, status_t, -- cgit v1.2.3 From 9e40e3e9fa2d450dc2cce10130423206884f21c9 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 21 Nov 2011 11:51:16 +0100 Subject: Added message encoding rules for quick mode --- src/libcharon/encoding/message.c | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index afa9b1956..7535f412c 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -575,6 +575,63 @@ static payload_order_t informational_i_order_v1[] = { {DELETE_V1, 0}, {VENDOR_ID_V1, 0}, }; + +/** + * Message rule for QUICK_MODE from initiator. + */ +static payload_rule_t quick_mode_i_rules[] = { +/* payload type min max encr suff */ + {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, + {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, + {HASH_V1, 0, 1, TRUE, FALSE}, + {SECURITY_ASSOCIATION_V1, 0, 2, TRUE, FALSE}, + {NONCE_V1, 0, 1, TRUE, FALSE}, + {KEY_EXCHANGE_V1, 0, 1, TRUE, FALSE}, + {ID_V1, 0, 2, TRUE, FALSE}, +}; + +/** + * payload order for QUICK_MODE from initiator. + */ +static payload_order_t quick_mode_i_order[] = { +/* payload type notify type */ + {NOTIFY_V1, 0}, + {VENDOR_ID_V1, 0}, + {HASH_V1, 0}, + {SECURITY_ASSOCIATION_V1, 0}, + {NONCE_V1, 0}, + {KEY_EXCHANGE_V1, 0}, + {ID_V1, 0}, +}; + +/** + * Message rule for QUICK_MODE from responder. + */ +static payload_rule_t quick_mode_r_rules[] = { +/* payload type min max encr suff */ + {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, + {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, + {HASH_V1, 0, 1, TRUE, FALSE}, + {SECURITY_ASSOCIATION_V1, 0, 2, TRUE, FALSE}, + {NONCE_V1, 0, 1, TRUE, FALSE}, + {KEY_EXCHANGE_V1, 0, 1, TRUE, FALSE}, + {ID_V1, 0, 2, TRUE, FALSE}, +}; + +/** + * payload order for QUICK_MODE from responder. + */ +static payload_order_t quick_mode_r_order[] = { +/* payload type notify type */ + {NOTIFY_V1, 0}, + {VENDOR_ID_V1, 0}, + {HASH_V1, 0}, + {SECURITY_ASSOCIATION_V1, 0}, + {NONCE_V1, 0}, + {KEY_EXCHANGE_V1, 0}, + {ID_V1, 0}, +}; + #endif /* USE_IKEV1 */ /** @@ -644,6 +701,14 @@ static message_rule_t message_rules[] = { countof(informational_i_rules_v1), informational_i_rules_v1, countof(informational_i_order_v1), informational_i_order_v1, }, + {QUICK_MODE, TRUE, TRUE, + countof(quick_mode_i_rules), quick_mode_i_rules, + countof(quick_mode_i_order), quick_mode_i_order, + }, + {QUICK_MODE, FALSE, TRUE, + countof(quick_mode_r_rules), quick_mode_r_rules, + countof(quick_mode_r_order), quick_mode_r_order, + }, /* TODO-IKEv1: define rules for other exchanges */ #endif /* USE_IKEV1 */ }; -- cgit v1.2.3 From 3bd5fcc8328af1241599e8bf0ef673d120dff798 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 21 Nov 2011 11:54:29 +0100 Subject: Print message ID as unsigned integer --- src/libcharon/encoding/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 7535f412c..2bd52ec4c 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1100,7 +1100,7 @@ static char* get_string(private_message_t *this, char *buf, int len) memset(buf, 0, len); len--; - written = snprintf(pos, len, "%N %s %d [", + written = snprintf(pos, len, "%N %s %u [", exchange_type_names, this->exchange_type, this->is_request ? "request" : "response", this->message_id); -- cgit v1.2.3 From 0cec72df400b7009c839248872b030450d20fe02 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 21 Nov 2011 11:18:08 +0100 Subject: Provide keymat_t to message_t to encrypt/decrypt data. --- src/libcharon/encoding/message.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 2bd52ec4c..79cc86ed4 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -24,10 +24,8 @@ #include #include -#include #include #include -#include #include #include #include @@ -1334,13 +1332,14 @@ METHOD(message_t, disable_sort, void, } METHOD(message_t, generate, status_t, - private_message_t *this, aead_t *aead, packet_t **packet) + private_message_t *this, keymat_t *keymat, packet_t **packet) { generator_t *generator; ike_header_t *ike_header; payload_t *payload, *next; encryption_payload_t *encryption = NULL; enumerator_t *enumerator; + aead_t *aead; chunk_t chunk; char str[BUF_LEN]; u_int32_t *lenpos; @@ -1374,6 +1373,7 @@ METHOD(message_t, generate, status_t, DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str))); + aead = keymat->get_aead(keymat, FALSE); if (aead && this->rule->encrypted) { encryption = wrap_payloads(this); @@ -1609,13 +1609,14 @@ static status_t parse_payloads(private_message_t *this) /** * Decrypt payload from the encryption payload */ -static status_t decrypt_payloads(private_message_t *this, aead_t *aead) +static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat) { bool was_encrypted = FALSE; payload_t *payload, *previous = NULL; enumerator_t *enumerator; payload_rule_t *rule; payload_type_t type; + aead_t *aead; status_t status = SUCCESS; enumerator = this->payloads->create_enumerator(this->payloads); @@ -1641,6 +1642,7 @@ static status_t decrypt_payloads(private_message_t *this, aead_t *aead) status = VERIFY_ERROR; break; } + aead = keymat->get_aead(keymat, TRUE); encryption->set_transform(encryption, aead); chunk = this->packet->get_data(this->packet); if (chunk.len < encryption->get_length(encryption)) @@ -1752,7 +1754,7 @@ static status_t verify(private_message_t *this) } METHOD(message_t, parse_body, status_t, - private_message_t *this, aead_t *aead) + private_message_t *this, keymat_t *keymat) { status_t status = SUCCESS; char str[BUF_LEN]; @@ -1775,7 +1777,7 @@ METHOD(message_t, parse_body, status_t, return status; } - status = decrypt_payloads(this, aead); + status = decrypt_payloads(this, keymat); if (status != SUCCESS) { DBG1(DBG_ENC, "could not decrypt payloads"); @@ -1872,4 +1874,3 @@ message_t *message_create(int major, int minor) return this; } - -- cgit v1.2.3 From 477e856a15da725a674aa5783ff563c5123d230e Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 21 Nov 2011 13:19:19 +0100 Subject: Decrypt IKEv1 messages. --- src/libcharon/encoding/message.c | 46 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 79cc86ed4..a368d96cd 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -1566,6 +1567,23 @@ static status_t parse_payloads(private_message_t *this) payload_t *payload; status_t status; + if (this->is_encrypted) + { /* wrap the whole encrypted IKEv1 message in a special encryption + * payload which is then handled just like a regular payload */ + encryption_payload_t *encryption; + status = this->parser->parse_payload(this->parser, ENCRYPTED_V1, + (payload_t**)&encryption); + if (status != SUCCESS) + { + DBG1(DBG_ENC, "failed to wrap encrypted IKEv1 message"); + return PARSE_ERROR; + } + encryption->payload_interface.set_next_type((payload_t*)encryption, + this->first_payload); + this->payloads->insert_last(this->payloads, encryption); + return SUCCESS; + } + while (type != NO_PAYLOAD) { DBG2(DBG_ENC, "starting parsing a %N payload", @@ -1626,11 +1644,12 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat) DBG2(DBG_ENC, "process payload of type %N", payload_type_names, type); - if (type == ENCRYPTED) + if (type == ENCRYPTED || type == ENCRYPTED_V1) { encryption_payload_t *encryption; payload_t *encrypted; chunk_t chunk; + size_t bs; encryption = (encryption_payload_t*)payload; @@ -1643,15 +1662,29 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat) break; } aead = keymat->get_aead(keymat, TRUE); + bs = aead->get_block_size(aead); encryption->set_transform(encryption, aead); chunk = this->packet->get_data(this->packet); - if (chunk.len < encryption->get_length(encryption)) + if (chunk.len < encryption->get_length(encryption) || + chunk.len < bs) { DBG1(DBG_ENC, "invalid payload length"); status = VERIFY_ERROR; break; } - chunk.len -= encryption->get_length(encryption); + if (type == ENCRYPTED_V1) + { /* instead of associated data we provide the IV, we also update + * the IV with the last encrypted block */ + keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat; + chunk_t last_block = chunk_create(chunk.ptr + chunk.len - bs, + bs); + chunk = keymat_v1->get_iv(keymat_v1, this->message_id); + keymat_v1->update_iv(keymat_v1, this->message_id, last_block); + } + else + { + chunk.len -= encryption->get_length(encryption); + } status = encryption->decrypt(encryption, chunk); if (status != SUCCESS) { @@ -1792,6 +1825,13 @@ METHOD(message_t, parse_body, status_t, DBG1(DBG_ENC, "parsed %s", get_string(this, str, sizeof(str))); + if (this->is_encrypted) + { /* TODO-IKEv1: this should be done later when we know this is no + * retransmit */ + keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat; + keymat_v1->confirm_iv(keymat_v1, this->message_id); + } + return SUCCESS; } -- cgit v1.2.3 From c92f2cf36deca2d3917020fc8c41abb8ada316ca Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 21 Nov 2011 13:24:17 +0100 Subject: Encrypt IKEv1 messages. --- src/libcharon/encoding/message.c | 83 ++++++++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 17 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index a368d96cd..d088a7bf7 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1279,9 +1279,10 @@ static void order_payloads(private_message_t *this) } /** - * Wrap payloads in a encryption payload + * Wrap payloads in an encryption payload */ -static encryption_payload_t* wrap_payloads(private_message_t *this) +static encryption_payload_t* wrap_payloads(private_message_t *this, + payload_type_t encryption_type) { encryption_payload_t *encryption; linked_list_t *payloads; @@ -1295,7 +1296,7 @@ static encryption_payload_t* wrap_payloads(private_message_t *this) payloads->insert_last(payloads, current); } - encryption = encryption_payload_create(); + encryption = encryption_payload_create(encryption_type); while (payloads->remove_first(payloads, (void**)¤t) == SUCCESS) { payload_rule_t *rule; @@ -1308,8 +1309,8 @@ static encryption_payload_t* wrap_payloads(private_message_t *this) { encrypt = rule->encrypted; } - if (encrypt) - { + if (encrypt || this->is_encrypted) + { /* encryption is forced for IKEv1 */ DBG2(DBG_ENC, "insert payload %N to encryption payload", payload_type_names, type); encryption->add_payload(encryption, current); @@ -1335,16 +1336,18 @@ METHOD(message_t, disable_sort, void, METHOD(message_t, generate, status_t, private_message_t *this, keymat_t *keymat, packet_t **packet) { + keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat; generator_t *generator; ike_header_t *ike_header; payload_t *payload, *next; encryption_payload_t *encryption = NULL; + payload_type_t next_type; enumerator_t *enumerator; aead_t *aead; chunk_t chunk; char str[BUF_LEN]; u_int32_t *lenpos; - bool *reserved; + bool encrypted = FALSE, *reserved; int i; if (this->exchange_type == EXCHANGE_TYPE_UNDEFINED) @@ -1374,10 +1377,33 @@ METHOD(message_t, generate, status_t, DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str))); + if (this->major_version == IKEV2_MAJOR_VERSION) + { + encrypted = this->rule->encrypted; + } + else + { /* if at least one payload requires encryption, encrypt the message */ + /* TODO-IKEV1: set is_encrypted externally instead of this check? */ + enumerator = this->payloads->create_enumerator(this->payloads); + while (enumerator->enumerate(enumerator, (void**)&payload)) + { + payload_rule_t *rule; + rule = get_payload_rule(this, payload->get_type(payload)); + if (rule && rule->encrypted) + { + this->is_encrypted = TRUE; + encrypted = TRUE; + break; + } + } + enumerator->destroy(enumerator); + } + aead = keymat->get_aead(keymat, FALSE); - if (aead && this->rule->encrypted) + if (aead && encrypted) { - encryption = wrap_payloads(this); + encryption = wrap_payloads(this, this->is_encrypted ? ENCRYPTED_V1 + : ENCRYPTED); } else { @@ -1395,6 +1421,10 @@ METHOD(message_t, generate, status_t, ike_header->set_initiator_flag(ike_header, this->ike_sa_id->is_initiator(this->ike_sa_id)); } + else + { + ike_header->set_encryption_flag(ike_header, this->is_encrypted); + } ike_header->set_initiator_spi(ike_header, this->ike_sa_id->get_initiator_spi(this->ike_sa_id)); ike_header->set_responder_spi(ike_header, @@ -1422,20 +1452,32 @@ METHOD(message_t, generate, status_t, payload = next; } enumerator->destroy(enumerator); - payload->set_next_type(payload, encryption ? ENCRYPTED : NO_PAYLOAD); + if (this->is_encrypted) + { /* for encrypted IKEv1 messages */ + next_type = encryption->payload_interface.get_next_type( + (payload_t*)encryption); + } + else + { + next_type = encryption ? ENCRYPTED : NO_PAYLOAD; + } + payload->set_next_type(payload, next_type); generator->generate_payload(generator, payload); ike_header->destroy(ike_header); if (encryption) { - u_int32_t *lenpos; - - /* build associated data (without header of encryption payload) */ - chunk = generator->get_chunk(generator, &lenpos); + if (this->is_encrypted) + { /* for IKEv1 instead of associated data we provide the IV */ + chunk = keymat_v1->get_iv(keymat_v1, this->message_id); + } + else + { /* build associated data (without header of encryption payload) */ + chunk = generator->get_chunk(generator, &lenpos); + /* fill in length, including encryption payload */ + htoun32(lenpos, chunk.len + encryption->get_length(encryption)); + } encryption->set_transform(encryption, aead); - /* fill in length, including encryption payload */ - htoun32(lenpos, chunk.len + encryption->get_length(encryption)); - this->payloads->insert_last(this->payloads, encryption); if (!encryption->encrypt(encryption, chunk)) { @@ -1447,8 +1489,15 @@ METHOD(message_t, generate, status_t, chunk = generator->get_chunk(generator, &lenpos); htoun32(lenpos, chunk.len); this->packet->set_data(this->packet, chunk_clone(chunk)); + if (this->is_encrypted) + { /* update the IV for the next IKEv1 message */ + chunk_t last_block; + size_t bs = aead->get_block_size(aead); + last_block = chunk_create(chunk.ptr + chunk.len - bs, bs); + keymat_v1->update_iv(keymat_v1, this->message_id, last_block); + keymat_v1->confirm_iv(keymat_v1, this->message_id); + } generator->destroy(generator); - *packet = this->packet->clone(this->packet); return SUCCESS; } -- cgit v1.2.3 From d66199884f92ff157e8702a5cf6f83c7fdc6fdd7 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Mon, 21 Nov 2011 13:26:27 +0100 Subject: Set flags on message according to IKE version when parsing header. --- src/libcharon/encoding/message.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index d088a7bf7..e7a48344b 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1559,10 +1559,16 @@ METHOD(message_t, parse_header, status_t, this->exchange_type = ike_header->get_exchange_type(ike_header); this->message_id = ike_header->get_message_id(ike_header); - this->is_request = !ike_header->get_response_flag(ike_header); - this->is_encrypted = ike_header->get_encryption_flag(ike_header); this->major_version = ike_header->get_maj_version(ike_header); this->minor_version = ike_header->get_min_version(ike_header); + if (this->major_version == IKEV2_MAJOR_VERSION) + { + this->is_request = !ike_header->get_response_flag(ike_header); + } + else + { + this->is_encrypted = ike_header->get_encryption_flag(ike_header); + } this->first_payload = ike_header->payload_interface.get_next_type( &ike_header->payload_interface); for (i = 0; i < countof(this->reserved); i++) -- cgit v1.2.3 From 54a8a94fa9009437e4c4d7df52d881fc1203c2ac Mon Sep 17 00:00:00 2001 From: Clavister OpenSource Date: Wed, 23 Nov 2011 08:29:54 +0100 Subject: IKEv1 ConfigMode: Added TRANSACTION exchange type. Added attribute_payload (IKEv2 equiv cp_payload) and data_attribute (IKEv2 equiv configuration_attribute) payload types. Did not combine with IKEv2 because it wasn't trivial to do so. This might be a task worth investigating in the future, because there is a decent amount of shared code here. --- src/libcharon/encoding/message.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index e7a48344b..e84f9a123 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -631,6 +631,24 @@ static payload_order_t quick_mode_r_order[] = { {ID_V1, 0}, }; +/** + * Message rule for TRANSACTION. + */ +static payload_rule_t transaction_payload_rules_v1[] = { +/* payload type min max encr suff */ + {HASH_V1, 0, 1, TRUE, FALSE}, + {ATTRIBUTE_V1, 1, 1, FALSE, FALSE}, +}; + +/** + * Payload order for TRANSACTION. + */ +static payload_order_t transaction_payload_order_v1[] = { +/* payload type notify type */ + {HASH_V1, 0}, + {ATTRIBUTE_V1, 0}, +}; + #endif /* USE_IKEV1 */ /** @@ -708,6 +726,14 @@ static message_rule_t message_rules[] = { countof(quick_mode_r_rules), quick_mode_r_rules, countof(quick_mode_r_order), quick_mode_r_order, }, + {TRANSACTION, TRUE, TRUE, + countof(transaction_payload_rules_v1), transaction_payload_rules_v1, + countof(transaction_payload_order_v1), transaction_payload_order_v1, + }, + {TRANSACTION, FALSE, TRUE, + countof(transaction_payload_rules_v1), transaction_payload_rules_v1, + countof(transaction_payload_order_v1), transaction_payload_order_v1, + }, /* TODO-IKEv1: define rules for other exchanges */ #endif /* USE_IKEV1 */ }; -- cgit v1.2.3 From 017d98bf39e3824829cf17be1723b460a2ddeb4e Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 23 Nov 2011 11:26:04 +0100 Subject: Merged IKEv1 attribute payload/data into configuration payload/attribute --- src/libcharon/encoding/message.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index e84f9a123..032fc1b1c 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -635,9 +635,9 @@ static payload_order_t quick_mode_r_order[] = { * Message rule for TRANSACTION. */ static payload_rule_t transaction_payload_rules_v1[] = { -/* payload type min max encr suff */ - {HASH_V1, 0, 1, TRUE, FALSE}, - {ATTRIBUTE_V1, 1, 1, FALSE, FALSE}, +/* payload type min max encr suff */ + {HASH_V1, 0, 1, TRUE, FALSE}, + {CONFIGURATION_V1, 1, 1, FALSE, FALSE}, }; /** @@ -645,8 +645,8 @@ static payload_rule_t transaction_payload_rules_v1[] = { */ static payload_order_t transaction_payload_order_v1[] = { /* payload type notify type */ - {HASH_V1, 0}, - {ATTRIBUTE_V1, 0}, + {HASH_V1, 0}, + {CONFIGURATION_V1, 0}, }; #endif /* USE_IKEV1 */ -- cgit v1.2.3 From cd200cb821df307aec441308b74dbd8d94c73589 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 23 Nov 2011 13:17:46 +0100 Subject: Authenticate and verify Phase 2 IKEv1 messages with appropriate hashes. --- src/libcharon/encoding/message.c | 46 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 032fc1b1c..f53be0036 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -1408,7 +1409,19 @@ METHOD(message_t, generate, status_t, encrypted = this->rule->encrypted; } else - { /* if at least one payload requires encryption, encrypt the message */ + { + /* get a hash for this message, if any is required */ + chunk_t hash = keymat_v1->get_hash_phase2(keymat_v1, &this->public); + if (hash.ptr) + { /* insert a HASH payload as first payload */ + hash_payload_t *hash_payload = hash_payload_create(); + hash_payload->set_hash(hash_payload, hash); + this->payloads->insert_first(this->payloads, + (payload_t*)hash_payload); + chunk_free(&hash); + } + + /* if at least one payload requires encryption, encrypt the message */ /* TODO-IKEV1: set is_encrypted externally instead of this check? */ enumerator = this->payloads->create_enumerator(this->payloads); while (enumerator->enumerate(enumerator, (void**)&payload)) @@ -1821,7 +1834,7 @@ static status_t verify(private_message_t *this) DBG2(DBG_ENC, "verifying message structure"); - /* check for payloads with wrong count*/ + /* check for payloads with wrong count */ for (i = 0; i < this->rule->rule_count; i++) { enumerator_t *enumerator; @@ -1906,6 +1919,35 @@ METHOD(message_t, parse_body, status_t, DBG1(DBG_ENC, "parsed %s", get_string(this, str, sizeof(str))); + if (this->major_version == IKEV1_MAJOR_VERSION) + { + keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat; + chunk_t hash; + hash = keymat_v1->get_hash_phase2(keymat_v1, &this->public); + if (hash.ptr) + { + hash_payload_t *hash_payload; + chunk_t other_hash; + if (this->first_payload != HASH_V1) + { + DBG1(DBG_ENC, "expected HASH payload as first payload"); + chunk_free(&hash); + return VERIFY_ERROR; + } + hash_payload = (hash_payload_t*)get_payload(this, HASH_V1); + other_hash = hash_payload->get_hash(hash_payload); + if (!chunk_equals(hash, other_hash)) + { + DBG1(DBG_ENC, "our hash does not match received %B", + &other_hash); + chunk_free(&hash); + return VERIFY_ERROR; + } + DBG2(DBG_ENC, "verified IKEv1 message with hash %B", &hash); + chunk_free(&hash); + } + } + if (this->is_encrypted) { /* TODO-IKEv1: this should be done later when we know this is no * retransmit */ -- cgit v1.2.3 From d020d4d695c2d69ad5e29be2d97d6c33d89b9327 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 23 Nov 2011 14:41:07 +0100 Subject: Print message payload names after prepending IKEv1 HASH payload --- src/libcharon/encoding/message.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index f53be0036..440b014c0 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1402,8 +1402,6 @@ METHOD(message_t, generate, status_t, order_payloads(this); } - DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str))); - if (this->major_version == IKEV2_MAJOR_VERSION) { encrypted = this->rule->encrypted; @@ -1438,6 +1436,8 @@ METHOD(message_t, generate, status_t, enumerator->destroy(enumerator); } + DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str))); + aead = keymat->get_aead(keymat, FALSE); if (aead && encrypted) { -- cgit v1.2.3 From f4e21faa989998974e198ecb2d33521c612e29bf Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 23 Nov 2011 15:23:20 +0100 Subject: Fixed encryption of IKEv2 messages. --- src/libcharon/encoding/message.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 440b014c0..aa774e0c3 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1505,7 +1505,8 @@ METHOD(message_t, generate, status_t, ike_header->destroy(ike_header); if (encryption) - { + { /* set_transform() has to be called before get_length() */ + encryption->set_transform(encryption, aead); if (this->is_encrypted) { /* for IKEv1 instead of associated data we provide the IV */ chunk = keymat_v1->get_iv(keymat_v1, this->message_id); @@ -1516,7 +1517,6 @@ METHOD(message_t, generate, status_t, /* fill in length, including encryption payload */ htoun32(lenpos, chunk.len + encryption->get_length(encryption)); } - encryption->set_transform(encryption, aead); this->payloads->insert_last(this->payloads, encryption); if (!encryption->encrypt(encryption, chunk)) { -- cgit v1.2.3 From 983e852af87ec33cb30a96fe09414cc1646f360a Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 25 Nov 2011 17:45:30 +0100 Subject: Handle INFORMATIONAL_V1 messages when no keys have been derived yet. This allows to gracefully process the INFORMATIONAL_V1 message rules which require the payloads to be encrypted and thus the exchange to be authenticated with a HASH payload. If such an exchange is now initiated before the ISAKMP_SA is established, the message is simply sent unencrypted and without HASH payload. --- src/libcharon/encoding/message.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index aa774e0c3..17adc5eb9 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1419,8 +1419,8 @@ METHOD(message_t, generate, status_t, chunk_free(&hash); } - /* if at least one payload requires encryption, encrypt the message */ - /* TODO-IKEV1: set is_encrypted externally instead of this check? */ + /* if at least one payload requires encryption, encrypt the message. + * if we have no key material available, the flag will be reset below */ enumerator = this->payloads->create_enumerator(this->payloads); while (enumerator->enumerate(enumerator, (void**)&payload)) { @@ -1447,6 +1447,7 @@ METHOD(message_t, generate, status_t, else { DBG2(DBG_ENC, "not encrypting payloads"); + this->is_encrypted = FALSE; } ike_header = ike_header_create_version(this->major_version, -- cgit v1.2.3 From 29a5e0707eb6cb1fd3f23b399af8f2fa0e7efe9b Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 25 Nov 2011 17:58:37 +0100 Subject: Handle unsupported IKEv1 exchange types more specifically. --- src/libcharon/encoding/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 17adc5eb9..3b45b7608 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1896,7 +1896,7 @@ METHOD(message_t, parse_body, status_t, DBG1(DBG_ENC, "no message rules specified for a %N %s", exchange_type_names, this->exchange_type, this->is_request ? "request" : "response"); - return PARSE_ERROR; + return NOT_SUPPORTED; } status = parse_payloads(this); -- cgit v1.2.3 From 37639e94fba52dad26f8205ac3c263b34e697720 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Fri, 25 Nov 2011 17:59:39 +0100 Subject: Handle invalid IKEv1 hashes more specifically. --- src/libcharon/encoding/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 3b45b7608..6c6004fac 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1942,7 +1942,7 @@ METHOD(message_t, parse_body, status_t, DBG1(DBG_ENC, "our hash does not match received %B", &other_hash); chunk_free(&hash); - return VERIFY_ERROR; + return FAILED; } DBG2(DBG_ENC, "verified IKEv1 message with hash %B", &hash); chunk_free(&hash); -- cgit v1.2.3 From 1e97783c993caec7f7556d6be5b7168701c31062 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 29 Nov 2011 11:14:25 +0100 Subject: Added payloads for IKEv1 NAT-Traversal negotiation. --- src/libcharon/encoding/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 6c6004fac..835073a5c 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1412,7 +1412,7 @@ METHOD(message_t, generate, status_t, chunk_t hash = keymat_v1->get_hash_phase2(keymat_v1, &this->public); if (hash.ptr) { /* insert a HASH payload as first payload */ - hash_payload_t *hash_payload = hash_payload_create(); + hash_payload_t *hash_payload = hash_payload_create(HASH_V1); hash_payload->set_hash(hash_payload, hash); this->payloads->insert_first(this->payloads, (payload_t*)hash_payload); -- cgit v1.2.3 From a0bea44a971baaa07704f34f94a09480af27b872 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 30 Nov 2011 16:55:24 +0100 Subject: Message rules for IKEv1 NAT-T payloads added. --- src/libcharon/encoding/message.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 835073a5c..b63264bf9 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -59,6 +59,11 @@ */ #define MAX_CERTREQ_PAYLOADS 5 +/** + * Max number of NAT-D payloads per IKEv1 message + */ +#define MAX_NAT_D_PAYLOADS 5 + /** * A payload rule defines the rules for a payload * in a specific message rule. It defines if and how @@ -431,6 +436,7 @@ static payload_rule_t id_prot_i_rules[] = { {NONCE_V1, 0, 1, FALSE, FALSE}, {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, + {NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE}, {ID_V1, 0, 1, TRUE, FALSE}, {CERTIFICATE_V1, 0, 1, TRUE, FALSE}, {SIGNATURE_V1, 0, 1, TRUE, FALSE}, @@ -452,6 +458,7 @@ static payload_order_t id_prot_i_order[] = { {CERTIFICATE_REQUEST_V1, 0}, {NOTIFY_V1, 0}, {VENDOR_ID_V1, 0}, + {NAT_D_V1, 0}, }; /** @@ -465,6 +472,7 @@ static payload_rule_t id_prot_r_rules[] = { {NONCE_V1, 0, 1, FALSE, FALSE}, {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, + {NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE}, {ID_V1, 0, 1, TRUE, FALSE}, {CERTIFICATE_V1, 0, 1, TRUE, FALSE}, {SIGNATURE_V1, 0, 1, TRUE, FALSE}, @@ -486,6 +494,7 @@ static payload_order_t id_prot_r_order[] = { {CERTIFICATE_REQUEST_V1, 0}, {NOTIFY_V1, 0}, {VENDOR_ID_V1, 0}, + {NAT_D_V1, 0}, }; /** @@ -499,6 +508,7 @@ static payload_rule_t aggressive_i_rules[] = { {NONCE_V1, 0, 1, FALSE, FALSE}, {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, + {NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE}, {ID_V1, 0, 1, FALSE, FALSE}, {CERTIFICATE_V1, 0, 1, FALSE, FALSE}, {SIGNATURE_V1, 0, 1, FALSE, FALSE}, @@ -515,6 +525,7 @@ static payload_order_t aggressive_i_order[] = { {NONCE_V1, 0}, {ID_V1, 0}, {CERTIFICATE_V1, 0}, + {NAT_D_V1, 0}, {SIGNATURE_V1, 0}, {HASH_V1, 0}, {CERTIFICATE_REQUEST_V1, 0}, @@ -533,6 +544,7 @@ static payload_rule_t aggressive_r_rules[] = { {NONCE_V1, 0, 1, FALSE, FALSE}, {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, + {NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE}, {ID_V1, 0, 1, FALSE, FALSE}, {CERTIFICATE_V1, 0, 1, FALSE, FALSE}, {SIGNATURE_V1, 0, 1, FALSE, FALSE}, @@ -549,6 +561,7 @@ static payload_order_t aggressive_r_order[] = { {NONCE_V1, 0}, {ID_V1, 0}, {CERTIFICATE_V1, 0}, + {NAT_D_V1, 0}, {SIGNATURE_V1, 0}, {HASH_V1, 0}, {CERTIFICATE_REQUEST_V1, 0}, @@ -588,6 +601,7 @@ static payload_rule_t quick_mode_i_rules[] = { {NONCE_V1, 0, 1, TRUE, FALSE}, {KEY_EXCHANGE_V1, 0, 1, TRUE, FALSE}, {ID_V1, 0, 2, TRUE, FALSE}, + {NAT_OA_V1, 0, 2, TRUE, FALSE}, }; /** @@ -602,6 +616,7 @@ static payload_order_t quick_mode_i_order[] = { {NONCE_V1, 0}, {KEY_EXCHANGE_V1, 0}, {ID_V1, 0}, + {NAT_OA_V1, 0}, }; /** @@ -616,6 +631,7 @@ static payload_rule_t quick_mode_r_rules[] = { {NONCE_V1, 0, 1, TRUE, FALSE}, {KEY_EXCHANGE_V1, 0, 1, TRUE, FALSE}, {ID_V1, 0, 2, TRUE, FALSE}, + {NAT_OA_V1, 0, 2, TRUE, FALSE}, }; /** @@ -630,6 +646,7 @@ static payload_order_t quick_mode_r_order[] = { {NONCE_V1, 0}, {KEY_EXCHANGE_V1, 0}, {ID_V1, 0}, + {NAT_OA_V1, 0}, }; /** -- cgit v1.2.3 From 07abb470c661cc2df1005b01ad17e1564f32384e Mon Sep 17 00:00:00 2001 From: Clavister OpenSource Date: Fri, 2 Dec 2011 16:22:42 +0100 Subject: IKEv1: Added basic support for INFORMATIONAL exchange types, and for NOTIFY_V1 messages in the 3rd message in quick_mode. --- src/libcharon/encoding/message.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index b63264bf9..0a808ac02 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -574,6 +574,7 @@ static payload_order_t aggressive_r_order[] = { */ static payload_rule_t informational_i_rules_v1[] = { /* payload type min max encr suff */ + {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, {DELETE_V1, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE}, {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, @@ -1946,22 +1947,25 @@ METHOD(message_t, parse_body, status_t, { hash_payload_t *hash_payload; chunk_t other_hash; - if (this->first_payload != HASH_V1) + if ((this->first_payload != HASH_V1) && (this->public.get_exchange_type(&this->public) != INFORMATIONAL_V1)) { DBG1(DBG_ENC, "expected HASH payload as first payload"); chunk_free(&hash); return VERIFY_ERROR; } - hash_payload = (hash_payload_t*)get_payload(this, HASH_V1); - other_hash = hash_payload->get_hash(hash_payload); - if (!chunk_equals(hash, other_hash)) + if (this->first_payload == HASH_V1) { - DBG1(DBG_ENC, "our hash does not match received %B", - &other_hash); - chunk_free(&hash); - return FAILED; + hash_payload = (hash_payload_t*)get_payload(this, HASH_V1); + other_hash = hash_payload->get_hash(hash_payload); + if (!chunk_equals(hash, other_hash)) + { + DBG1(DBG_ENC, "our hash does not match received %B", + &other_hash); + chunk_free(&hash); + return FAILED; + } + DBG2(DBG_ENC, "verified IKEv1 message with hash %B", &hash); } - DBG2(DBG_ENC, "verified IKEv1 message with hash %B", &hash); chunk_free(&hash); } } -- cgit v1.2.3 From 7d9269bfce9ab02e614b41c12178174aad2d42de Mon Sep 17 00:00:00 2001 From: Clavister OpenSource Date: Mon, 5 Dec 2011 14:11:48 +0100 Subject: certificate handling for XAuth responder. --- src/libcharon/encoding/message.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100644 => 100755 src/libcharon/encoding/message.c (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c old mode 100644 new mode 100755 index 0a808ac02..5b79ac733 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -438,7 +438,7 @@ static payload_rule_t id_prot_i_rules[] = { {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, {NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE}, {ID_V1, 0, 1, TRUE, FALSE}, - {CERTIFICATE_V1, 0, 1, TRUE, FALSE}, + {CERTIFICATE_V1, 0, 2, TRUE, FALSE}, {SIGNATURE_V1, 0, 1, TRUE, FALSE}, {HASH_V1, 0, 1, TRUE, FALSE}, }; @@ -474,7 +474,7 @@ static payload_rule_t id_prot_r_rules[] = { {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, {NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE}, {ID_V1, 0, 1, TRUE, FALSE}, - {CERTIFICATE_V1, 0, 1, TRUE, FALSE}, + {CERTIFICATE_V1, 0, 2, TRUE, FALSE}, {SIGNATURE_V1, 0, 1, TRUE, FALSE}, {HASH_V1, 0, 1, TRUE, FALSE}, }; -- cgit v1.2.3 From 5d1eeec297de5009056d71e65c336987ee0fe10f Mon Sep 17 00:00:00 2001 From: Clavister OpenSource Date: Wed, 7 Dec 2011 13:30:53 +0100 Subject: Handle incoming delete messages --- src/libcharon/encoding/message.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 5b79ac733..91131ad22 100755 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -590,6 +590,27 @@ static payload_order_t informational_i_order_v1[] = { {VENDOR_ID_V1, 0}, }; +/** + * Message rule for INFORMATIONAL_V1 from responder. + */ +static payload_rule_t informational_r_rules_v1[] = { +/* payload type min max encr suff */ + {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, FALSE, FALSE}, + {NOTIFY_V1, 0, MAX_NOTIFY_PAYLOADS, TRUE, FALSE}, + {DELETE_V1, 0, MAX_DELETE_PAYLOADS, TRUE, FALSE}, + {VENDOR_ID_V1, 0, MAX_VID_PAYLOADS, TRUE, FALSE}, +}; + +/** + * payload order for INFORMATIONAL_V1 from responder. + */ +static payload_order_t informational_r_order_v1[] = { +/* payload type notify type */ + {NOTIFY_V1, 0}, + {DELETE_V1, 0}, + {VENDOR_ID_V1, 0}, +}; + /** * Message rule for QUICK_MODE from initiator. */ @@ -737,6 +758,10 @@ static message_rule_t message_rules[] = { countof(informational_i_rules_v1), informational_i_rules_v1, countof(informational_i_order_v1), informational_i_order_v1, }, + {INFORMATIONAL_V1, FALSE, TRUE, + countof(informational_r_rules_v1), informational_r_rules_v1, + countof(informational_r_order_v1), informational_r_order_v1, + }, {QUICK_MODE, TRUE, TRUE, countof(quick_mode_i_rules), quick_mode_i_rules, countof(quick_mode_i_order), quick_mode_i_order, -- cgit v1.2.3 From b8383f1f2dd2202bf2dc8b7e78851a22ead6603a Mon Sep 17 00:00:00 2001 From: Clavister OpenSource Date: Fri, 9 Dec 2011 16:04:12 +0100 Subject: Encrypt INFORMATIONAL exchange if needed --- src/libcharon/encoding/message.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 91131ad22..1296475d5 100755 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1459,24 +1459,35 @@ METHOD(message_t, generate, status_t, hash_payload->set_hash(hash_payload, hash); this->payloads->insert_first(this->payloads, (payload_t*)hash_payload); + + if (this->exchange_type == INFORMATIONAL_V1) + { + DBG3(DBG_ENC, "encrypting IKEv1 INFORMATIONAL exchange message"); + this->is_encrypted = TRUE; + encrypted = TRUE; + } + chunk_free(&hash); } - /* if at least one payload requires encryption, encrypt the message. - * if we have no key material available, the flag will be reset below */ - enumerator = this->payloads->create_enumerator(this->payloads); - while (enumerator->enumerate(enumerator, (void**)&payload)) + if (!encrypted) { - payload_rule_t *rule; - rule = get_payload_rule(this, payload->get_type(payload)); - if (rule && rule->encrypted) + /* if at least one payload requires encryption, encrypt the message. + * if we have no key material available, the flag will be reset below */ + enumerator = this->payloads->create_enumerator(this->payloads); + while (enumerator->enumerate(enumerator, (void**)&payload)) { - this->is_encrypted = TRUE; - encrypted = TRUE; - break; + payload_rule_t *rule; + rule = get_payload_rule(this, payload->get_type(payload)); + if (rule && rule->encrypted) + { + this->is_encrypted = TRUE; + encrypted = TRUE; + break; + } } + enumerator->destroy(enumerator); } - enumerator->destroy(enumerator); } DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str))); -- cgit v1.2.3 From 3ba15819edb44d00f5c9f8ad06ea7e78a48515c4 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 14 Dec 2011 16:46:29 +0100 Subject: Remove executable flag from source code files --- src/libcharon/encoding/message.c | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 src/libcharon/encoding/message.c (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c old mode 100755 new mode 100644 -- cgit v1.2.3 From a4cc07136481f1ce9960d7d366b942f40ae5b451 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 15 Dec 2011 16:23:47 +0100 Subject: Do not trust unprotected INFORMATIONALS, just print that we got one --- src/libcharon/encoding/message.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 1296475d5..1c6e6943c 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1983,25 +1983,30 @@ METHOD(message_t, parse_body, status_t, { hash_payload_t *hash_payload; chunk_t other_hash; - if ((this->first_payload != HASH_V1) && (this->public.get_exchange_type(&this->public) != INFORMATIONAL_V1)) + if (this->first_payload != HASH_V1) { - DBG1(DBG_ENC, "expected HASH payload as first payload"); + if (this->exchange_type == INFORMATIONAL_V1) + { /* TODO-IKEv1: Parse and log contents? */ + DBG1(DBG_ENC, "ignoring unprotected INFORMATIONAL from %H", + this->packet->get_source(this->packet)); + } + else + { + DBG1(DBG_ENC, "expected HASH payload as first payload"); + } chunk_free(&hash); return VERIFY_ERROR; } - if (this->first_payload == HASH_V1) + hash_payload = (hash_payload_t*)get_payload(this, HASH_V1); + other_hash = hash_payload->get_hash(hash_payload); + if (!chunk_equals(hash, other_hash)) { - hash_payload = (hash_payload_t*)get_payload(this, HASH_V1); - other_hash = hash_payload->get_hash(hash_payload); - if (!chunk_equals(hash, other_hash)) - { - DBG1(DBG_ENC, "our hash does not match received %B", - &other_hash); - chunk_free(&hash); - return FAILED; - } - DBG2(DBG_ENC, "verified IKEv1 message with hash %B", &hash); + DBG1(DBG_ENC, "our hash does not match received %B", + &other_hash); + chunk_free(&hash); + return FAILED; } + DBG2(DBG_ENC, "verified IKEv1 message with hash %B", &hash); chunk_free(&hash); } } -- cgit v1.2.3 From b9a707e696148fad420df508462abbaf734bc646 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Sat, 17 Dec 2011 12:47:44 +0100 Subject: Some coding style cleanups --- src/libcharon/encoding/message.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 1c6e6943c..532b00a5c 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1825,8 +1825,9 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat) { /* instead of associated data we provide the IV, we also update * the IV with the last encrypted block */ keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat; - chunk_t last_block = chunk_create(chunk.ptr + chunk.len - bs, - bs); + chunk_t last_block; + + last_block = chunk_create(chunk.ptr + chunk.len - bs, bs); chunk = keymat_v1->get_iv(keymat_v1, this->message_id); keymat_v1->update_iv(keymat_v1, this->message_id, last_block); } @@ -1978,15 +1979,17 @@ METHOD(message_t, parse_body, status_t, { keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat; chunk_t hash; + hash = keymat_v1->get_hash_phase2(keymat_v1, &this->public); if (hash.ptr) { hash_payload_t *hash_payload; chunk_t other_hash; + if (this->first_payload != HASH_V1) { if (this->exchange_type == INFORMATIONAL_V1) - { /* TODO-IKEv1: Parse and log contents? */ + { DBG1(DBG_ENC, "ignoring unprotected INFORMATIONAL from %H", this->packet->get_source(this->packet)); } -- cgit v1.2.3 From 5d0458af0aef7b3161957bec95016e728efc3c2d Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 19 Dec 2011 10:12:33 +0100 Subject: Another set of cleanups in message.c --- src/libcharon/encoding/message.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 532b00a5c..708e3fb97 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1351,8 +1351,7 @@ static void order_payloads(private_message_t *this) /** * Wrap payloads in an encryption payload */ -static encryption_payload_t* wrap_payloads(private_message_t *this, - payload_type_t encryption_type) +static encryption_payload_t* wrap_payloads(private_message_t *this) { encryption_payload_t *encryption; linked_list_t *payloads; @@ -1366,7 +1365,14 @@ static encryption_payload_t* wrap_payloads(private_message_t *this, payloads->insert_last(payloads, current); } - encryption = encryption_payload_create(encryption_type); + if (this->is_encrypted) + { + encryption = encryption_payload_create(ENCRYPTED_V1); + } + else + { + encryption = encryption_payload_create(ENCRYPTED); + } while (payloads->remove_first(payloads, (void**)¤t) == SUCCESS) { payload_rule_t *rule; @@ -1455,34 +1461,30 @@ METHOD(message_t, generate, status_t, chunk_t hash = keymat_v1->get_hash_phase2(keymat_v1, &this->public); if (hash.ptr) { /* insert a HASH payload as first payload */ - hash_payload_t *hash_payload = hash_payload_create(HASH_V1); - hash_payload->set_hash(hash_payload, hash); - this->payloads->insert_first(this->payloads, - (payload_t*)hash_payload); + hash_payload_t *hash_payload; + hash_payload = hash_payload_create(HASH_V1); + hash_payload->set_hash(hash_payload, hash); + this->payloads->insert_first(this->payloads, hash_payload); if (this->exchange_type == INFORMATIONAL_V1) { - DBG3(DBG_ENC, "encrypting IKEv1 INFORMATIONAL exchange message"); - this->is_encrypted = TRUE; - encrypted = TRUE; + this->is_encrypted = encrypted = TRUE; } - chunk_free(&hash); } - if (!encrypted) { - /* if at least one payload requires encryption, encrypt the message. - * if we have no key material available, the flag will be reset below */ + /* If at least one payload requires encryption, encrypt the message. + * If no key material is available, the flag will be reset below. */ enumerator = this->payloads->create_enumerator(this->payloads); while (enumerator->enumerate(enumerator, (void**)&payload)) { payload_rule_t *rule; + rule = get_payload_rule(this, payload->get_type(payload)); if (rule && rule->encrypted) { - this->is_encrypted = TRUE; - encrypted = TRUE; + this->is_encrypted = encrypted = TRUE; break; } } @@ -1495,8 +1497,7 @@ METHOD(message_t, generate, status_t, aead = keymat->get_aead(keymat, FALSE); if (aead && encrypted) { - encryption = wrap_payloads(this, this->is_encrypted ? ENCRYPTED_V1 - : ENCRYPTED); + encryption = wrap_payloads(this); } else { -- cgit v1.2.3 From 15a682f4c23d0b8340b31077698e6f6d924c2861 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 19 Dec 2011 13:10:29 +0100 Subject: Separated libcharon/sa directory with ikev1 and ikev2 subfolders --- src/libcharon/encoding/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 708e3fb97..cf2a66efa 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include -- cgit v1.2.3 From 82b1e5e270a2cd15edede0cbb216d7e9be1152d4 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 20 Dec 2011 16:07:00 +0100 Subject: Accept NULL as keymat when generating a message --- src/libcharon/encoding/message.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index cf2a66efa..2bf44cb3a 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1419,8 +1419,8 @@ METHOD(message_t, generate, status_t, encryption_payload_t *encryption = NULL; payload_type_t next_type; enumerator_t *enumerator; - aead_t *aead; - chunk_t chunk; + aead_t *aead = NULL; + chunk_t chunk, hash = chunk_empty; char str[BUF_LEN]; u_int32_t *lenpos; bool encrypted = FALSE, *reserved; @@ -1458,7 +1458,10 @@ METHOD(message_t, generate, status_t, else { /* get a hash for this message, if any is required */ - chunk_t hash = keymat_v1->get_hash_phase2(keymat_v1, &this->public); + if (keymat_v1) + { + hash = keymat_v1->get_hash_phase2(keymat_v1, &this->public); + } if (hash.ptr) { /* insert a HASH payload as first payload */ hash_payload_t *hash_payload; @@ -1494,7 +1497,10 @@ METHOD(message_t, generate, status_t, DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str))); - aead = keymat->get_aead(keymat, FALSE); + if (keymat) + { + aead = keymat->get_aead(keymat, FALSE); + } if (aead && encrypted) { encryption = wrap_payloads(this); -- cgit v1.2.3 From 07b8ec7c00626f2bbf8fa3e9aded9df520d50221 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 21 Dec 2011 12:39:21 +0100 Subject: Cast keymat safely, not based on external input --- src/libcharon/encoding/message.c | 80 ++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 36 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 2bf44cb3a..46384a5ac 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1450,18 +1450,10 @@ METHOD(message_t, generate, status_t, { order_payloads(this); } - - if (this->major_version == IKEV2_MAJOR_VERSION) - { - encrypted = this->rule->encrypted; - } - else + if (keymat && keymat->get_version(keymat) == IKEV1) { /* get a hash for this message, if any is required */ - if (keymat_v1) - { - hash = keymat_v1->get_hash_phase2(keymat_v1, &this->public); - } + hash = keymat_v1->get_hash_phase2(keymat_v1, &this->public); if (hash.ptr) { /* insert a HASH payload as first payload */ hash_payload_t *hash_payload; @@ -1475,24 +1467,28 @@ METHOD(message_t, generate, status_t, } chunk_free(&hash); } - if (!encrypted) + } + if (this->major_version == IKEV2_MAJOR_VERSION) + { + encrypted = this->rule->encrypted; + } + else if (!encrypted) + { + /* If at least one payload requires encryption, encrypt the message. + * If no key material is available, the flag will be reset below. */ + enumerator = this->payloads->create_enumerator(this->payloads); + while (enumerator->enumerate(enumerator, (void**)&payload)) { - /* If at least one payload requires encryption, encrypt the message. - * If no key material is available, the flag will be reset below. */ - enumerator = this->payloads->create_enumerator(this->payloads); - while (enumerator->enumerate(enumerator, (void**)&payload)) - { - payload_rule_t *rule; + payload_rule_t *rule; - rule = get_payload_rule(this, payload->get_type(payload)); - if (rule && rule->encrypted) - { - this->is_encrypted = encrypted = TRUE; - break; - } + rule = get_payload_rule(this, payload->get_type(payload)); + if (rule && rule->encrypted) + { + this->is_encrypted = encrypted = TRUE; + break; } - enumerator->destroy(enumerator); } + enumerator->destroy(enumerator); } DBG1(DBG_ENC, "generating %s", get_string(this, str, sizeof(str))); @@ -1591,9 +1587,12 @@ METHOD(message_t, generate, status_t, htoun32(lenpos, chunk.len); this->packet->set_data(this->packet, chunk_clone(chunk)); if (this->is_encrypted) - { /* update the IV for the next IKEv1 message */ + { + /* update the IV for the next IKEv1 message */ chunk_t last_block; - size_t bs = aead->get_block_size(aead); + size_t bs; + + bs = aead->get_block_size(aead); last_block = chunk_create(chunk.ptr + chunk.len - bs, bs); keymat_v1->update_iv(keymat_v1, this->message_id, last_block); keymat_v1->confirm_iv(keymat_v1, this->message_id); @@ -1727,6 +1726,7 @@ static status_t parse_payloads(private_message_t *this) { /* wrap the whole encrypted IKEv1 message in a special encryption * payload which is then handled just like a regular payload */ encryption_payload_t *encryption; + status = this->parser->parse_payload(this->parser, ENCRYPTED_V1, (payload_t**)&encryption); if (status != SUCCESS) @@ -1817,7 +1817,19 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat) status = VERIFY_ERROR; break; } + if (!keymat) + { + DBG1(DBG_ENC, "found encryption payload, but no keymat"); + status = INVALID_ARG; + break; + } aead = keymat->get_aead(keymat, TRUE); + if (!aead) + { + DBG1(DBG_ENC, "found encryption payload, but no transform set"); + status = INVALID_ARG; + break; + } bs = aead->get_block_size(aead); encryption->set_transform(encryption, aead); chunk = this->packet->get_data(this->packet); @@ -1828,7 +1840,7 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat) status = VERIFY_ERROR; break; } - if (type == ENCRYPTED_V1) + if (keymat->get_version(keymat) == IKEV1) { /* instead of associated data we provide the IV, we also update * the IV with the last encrypted block */ keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat; @@ -1982,7 +1994,7 @@ METHOD(message_t, parse_body, status_t, DBG1(DBG_ENC, "parsed %s", get_string(this, str, sizeof(str))); - if (this->major_version == IKEV1_MAJOR_VERSION) + if (keymat && keymat->get_version(keymat) == IKEV1) { keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat; chunk_t hash; @@ -2019,15 +2031,11 @@ METHOD(message_t, parse_body, status_t, DBG2(DBG_ENC, "verified IKEv1 message with hash %B", &hash); chunk_free(&hash); } + if (this->is_encrypted) + { /* message verified, confirm IV */ + keymat_v1->confirm_iv(keymat_v1, this->message_id); + } } - - if (this->is_encrypted) - { /* TODO-IKEv1: this should be done later when we know this is no - * retransmit */ - keymat_v1_t *keymat_v1 = (keymat_v1_t*)keymat; - keymat_v1->confirm_iv(keymat_v1, this->message_id); - } - return SUCCESS; } -- cgit v1.2.3 From ebc7bcb55013245e74da596292e20dcbf6219a91 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 9 Jan 2012 17:10:18 +0100 Subject: Encrypt payloads of third aggressive mode message --- src/libcharon/encoding/message.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 46384a5ac..e6036177a 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -510,9 +510,9 @@ static payload_rule_t aggressive_i_rules[] = { {CERTIFICATE_REQUEST_V1, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, {NAT_D_V1, 0, MAX_NAT_D_PAYLOADS, FALSE, FALSE}, {ID_V1, 0, 1, FALSE, FALSE}, - {CERTIFICATE_V1, 0, 1, FALSE, FALSE}, - {SIGNATURE_V1, 0, 1, FALSE, FALSE}, - {HASH_V1, 0, 1, FALSE, FALSE}, + {CERTIFICATE_V1, 0, 1, TRUE, FALSE}, + {SIGNATURE_V1, 0, 1, TRUE, FALSE}, + {HASH_V1, 0, 1, TRUE, FALSE}, }; /** -- cgit v1.2.3 From bd8d1f1d9c96a816a7b172c05a9a51d6af22b758 Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 10 Jan 2012 10:58:29 +0100 Subject: Accept unencrypted Aggressive Mode messages. Racoon does not encrypt the third message during Aggressive Mode. --- src/libcharon/encoding/message.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index e6036177a..99aca870a 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1882,7 +1882,8 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat) encryption->destroy(encryption); } if (payload_is_known(type) && !was_encrypted && - !is_connectivity_check(this, payload)) + !is_connectivity_check(this, payload) && + this->exchange_type != AGGRESSIVE) { rule = get_payload_rule(this, type); if (!rule || rule->encrypted) -- cgit v1.2.3 From 5f2f864efc8f1ab0462c0f0edfd5af1ee5311728 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 10 Jan 2012 17:09:20 +0100 Subject: Support IKEv1 notifies in message_t.get_notify() --- src/libcharon/encoding/message.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 99aca870a..4ca119dd5 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1142,7 +1142,8 @@ METHOD(message_t, get_notify, notify_payload_t*, enumerator = create_payload_enumerator(this); while (enumerator->enumerate(enumerator, &payload)) { - if (payload->get_type(payload) == NOTIFY) + if (payload->get_type(payload) == NOTIFY || + payload->get_type(payload) == NOTIFY_V1) { notify = (notify_payload_t*)payload; if (notify->get_notify_type(notify) == type) -- cgit v1.2.3 From bb2d4e188270800e3b3574acad1f7e6b6fd51e48 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 10 Jan 2012 17:09:47 +0100 Subject: Print IKEv1 notify types in message summary --- src/libcharon/encoding/message.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 4ca119dd5..dd7f8ecc7 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1192,7 +1192,8 @@ static char* get_string(private_message_t *this, char *buf, int len) } pos += written; len -= written; - if (payload->get_type(payload) == NOTIFY) + if (payload->get_type(payload) == NOTIFY || + payload->get_type(payload) == NOTIFY_V1) { notify_payload_t *notify; notify_type_t type; -- cgit v1.2.3 From 1726795fa9abe4b32ecbd7abd721ecced6c9af9c Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Wed, 29 Feb 2012 14:47:09 +0100 Subject: Store the major IKE version on ike_sa_id_t. --- src/libcharon/encoding/message.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/libcharon/encoding/message.c') diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index dd7f8ecc7..63114c93d 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -1655,6 +1655,7 @@ METHOD(message_t, parse_header, status_t, DESTROY_IF(this->ike_sa_id); this->ike_sa_id = ike_sa_id_create( + ike_header->get_maj_version(ike_header), ike_header->get_initiator_spi(ike_header), ike_header->get_responder_spi(ike_header), ike_header->get_initiator_flag(ike_header)); -- cgit v1.2.3