diff options
author | Martin Willi <martin@revosec.ch> | 2012-03-20 17:56:18 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2012-03-20 17:57:53 +0100 |
commit | b1f2f05c926f3e36755bb3b2711bd1732c062047 (patch) | |
tree | 27f491ad55217d40051eb45db4de5a8a9217817a /src/libcharon/encoding/payloads/notify_payload.c | |
parent | 3cea55b0c819f90045a7ae5657ed476834b74746 (diff) | |
parent | d112a7e1feb583d011ba7868bb3b27b147dc2f68 (diff) | |
download | strongswan-b1f2f05c926f3e36755bb3b2711bd1732c062047.tar.bz2 strongswan-b1f2f05c926f3e36755bb3b2711bd1732c062047.tar.xz |
Merge branch 'ikev1-clean' into ikev1-master
Conflicts:
configure.in
man/ipsec.conf.5.in
src/libcharon/daemon.c
src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
src/libcharon/plugins/eap_radius/eap_radius_accounting.c
src/libcharon/plugins/eap_radius/eap_radius_forward.c
src/libcharon/plugins/farp/farp_listener.c
src/libcharon/sa/ike_sa.c
src/libcharon/sa/keymat.c
src/libcharon/sa/task_manager.c
src/libcharon/sa/trap_manager.c
src/libstrongswan/plugins/x509/x509_cert.c
src/libstrongswan/utils.h
Applied lost changes of moved files keymat.c and task_manager.c.
Updated listener_t.message hook signature in new plugins.
Diffstat (limited to 'src/libcharon/encoding/payloads/notify_payload.c')
-rwxr-xr-x[-rw-r--r--] | src/libcharon/encoding/payloads/notify_payload.c | 284 |
1 files changed, 209 insertions, 75 deletions
diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c index fef2949d3..411534491 100644..100755 --- a/src/libcharon/encoding/payloads/notify_payload.c +++ b/src/libcharon/encoding/payloads/notify_payload.c @@ -36,11 +36,18 @@ ENUM_NEXT(notify_type_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVALID_SYN "INVALID_MESSAGE_ID"); ENUM_NEXT(notify_type_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID, "INVALID_SPI"); -ENUM_NEXT(notify_type_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI, +ENUM_NEXT(notify_type_names, ATTRIBUTES_NOT_SUPPORTED, NO_PROPOSAL_CHOSEN, INVALID_SPI, + "ATTRIBUTES_NOT_SUPPORTED", "NO_PROPOSAL_CHOSEN"); -ENUM_NEXT(notify_type_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN, - "INVALID_KE_PAYLOAD"); -ENUM_NEXT(notify_type_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD, +ENUM_NEXT(notify_type_names, PAYLOAD_MALFORMED, AUTHENTICATION_FAILED, NO_PROPOSAL_CHOSEN, + "PAYLOAD_MALFORMED", + "INVALID_KE_PAYLOAD", + "INVALID_ID_INFORMATION", + "INVALID_CERT_ENCODING", + "INVALID_CERTIFICATE", + "CERT_TYPE_UNSUPPORTED", + "INVALID_CERT_AUTHORITY", + "INVALID_HASH_INFORMATION", "AUTHENTICATION_FAILED"); ENUM_NEXT(notify_type_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED, "SINGLE_PAIR_REQUIRED", @@ -99,7 +106,14 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, MS_NOTI "IKEV2_REPLAY_COUNTER_SYNC_SUPPORTED", "IKEV2_MESSAGE_ID_SYNC", "IPSEC_REPLAY_COUNTER_SYNC"); -ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, IPSEC_REPLAY_COUNTER_SYNC, +ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, IPSEC_REPLAY_COUNTER_SYNC, + "INITIAL_CONTACT"); +ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1, + "DPD_R_U_THERE", + "DPD_R_U_THERE_ACK"); +ENUM_NEXT(notify_type_names, UNITY_LOAD_BALANCE, UNITY_LOAD_BALANCE, DPD_R_U_THERE_ACK, + "UNITY_LOAD_BALANCE"); +ENUM_NEXT(notify_type_names, USE_BEET_MODE, USE_BEET_MODE, UNITY_LOAD_BALANCE, "USE_BEET_MODE"); ENUM_NEXT(notify_type_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE, "ME_MEDIATION", @@ -124,11 +138,18 @@ ENUM_NEXT(notify_type_short_names, INVALID_MESSAGE_ID, INVALID_MESSAGE_ID, INVAL "INVAL_MID"); ENUM_NEXT(notify_type_short_names, INVALID_SPI, INVALID_SPI, INVALID_MESSAGE_ID, "INVAL_SPI"); -ENUM_NEXT(notify_type_short_names, NO_PROPOSAL_CHOSEN, NO_PROPOSAL_CHOSEN, INVALID_SPI, +ENUM_NEXT(notify_type_short_names, ATTRIBUTES_NOT_SUPPORTED, NO_PROPOSAL_CHOSEN, INVALID_SPI, + "ATTR_UNSUP", "NO_PROP"); -ENUM_NEXT(notify_type_short_names, INVALID_KE_PAYLOAD, INVALID_KE_PAYLOAD, NO_PROPOSAL_CHOSEN, - "INVAL_KE"); -ENUM_NEXT(notify_type_short_names, AUTHENTICATION_FAILED, AUTHENTICATION_FAILED, INVALID_KE_PAYLOAD, +ENUM_NEXT(notify_type_short_names, PAYLOAD_MALFORMED, AUTHENTICATION_FAILED, NO_PROPOSAL_CHOSEN, + "PLD_MAL", + "INVAL_KE", + "INVAL_ID", + "INVAL_CERTEN", + "INVAL_CERT", + "CERT_UNSUP", + "INVAL_CA", + "INVAL_HASH", "AUTH_FAILED"); ENUM_NEXT(notify_type_short_names, SINGLE_PAIR_REQUIRED, CHILD_SA_NOT_FOUND, AUTHENTICATION_FAILED, "SINGLE_PAIR", @@ -187,7 +208,14 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, IPSEC_REPLAY_COUNTER_SYNC, M "RPL_CTR_SYN_SUP", "MSG_ID_SYN", "RPL_CTR_SYN"); -ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, IPSEC_REPLAY_COUNTER_SYNC, +ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, IPSEC_REPLAY_COUNTER_SYNC, + "INITIAL_CONTACT"); +ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1, + "DPD", + "DPD_ACK"); +ENUM_NEXT(notify_type_short_names, UNITY_LOAD_BALANCE, UNITY_LOAD_BALANCE, DPD_R_U_THERE_ACK, + "UNITY_LB"); +ENUM_NEXT(notify_type_short_names, USE_BEET_MODE, USE_BEET_MODE, UNITY_LOAD_BALANCE, "BEET_MODE"); ENUM_NEXT(notify_type_short_names, ME_MEDIATION, RADIUS_ATTRIBUTE, USE_BEET_MODE, "ME_MED", @@ -226,7 +254,7 @@ struct private_notify_payload_t { /** * reserved bits */ - bool reserved[7]; + bool reserved[8]; /** * Length of this payload. @@ -234,6 +262,11 @@ struct private_notify_payload_t { u_int16_t payload_length; /** + * Domain of interpretation, IKEv1 only. + */ + u_int32_t doi; + + /** * Protocol id. */ u_int8_t protocol_id; @@ -256,40 +289,42 @@ struct private_notify_payload_t { /** * Notification data. */ - chunk_t notification_data; + chunk_t notify_data; + + /** + * Type of payload, NOTIFY or NOTIFY_V1 + */ + payload_type_t type; }; /** - * Encoding rules to parse or generate a IKEv2-Notify Payload. - * - * The defined offsets are the positions in a object of type - * private_notify_payload_t. + * Encoding rules for an IKEv2 notification payload */ -encoding_rule_t notify_payload_encodings[] = { +static encoding_rule_t encodings_v2[] = { /* 1 Byte next payload type, stored in the field next_payload */ - { U_INT_8, offsetof(private_notify_payload_t, next_payload) }, + { U_INT_8, offsetof(private_notify_payload_t, next_payload) }, /* the critical bit */ - { FLAG, offsetof(private_notify_payload_t, critical) }, + { FLAG, offsetof(private_notify_payload_t, critical) }, /* 7 Bit reserved bits, nowhere stored */ - { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) }, - { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) }, - { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) }, - { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) }, - { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) }, - { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) }, - { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) }, /* Length of the whole payload*/ - { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) }, + { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) }, /* Protocol ID as 8 bit field*/ - { U_INT_8, offsetof(private_notify_payload_t, protocol_id) }, + { U_INT_8, offsetof(private_notify_payload_t, protocol_id) }, /* SPI Size as 8 bit field*/ - { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) }, + { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) }, /* Notify message type as 16 bit field*/ - { U_INT_16, offsetof(private_notify_payload_t, notify_type) }, + { U_INT_16, offsetof(private_notify_payload_t, notify_type) }, /* SPI as variable length field*/ - { SPI, offsetof(private_notify_payload_t, spi) }, + { SPI, offsetof(private_notify_payload_t, spi) }, /* Key Exchange Data is from variable size */ - { NOTIFICATION_DATA,offsetof(private_notify_payload_t, notification_data) } + { CHUNK_DATA, offsetof(private_notify_payload_t, notify_data) }, }; /* @@ -309,6 +344,57 @@ encoding_rule_t notify_payload_encodings[] = { ! ! +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ +/** + * Encoding rules for an IKEv1 notification payload + */ +static encoding_rule_t encodings_v1[] = { + /* 1 Byte next payload type, stored in the field next_payload */ + { U_INT_8, offsetof(private_notify_payload_t, next_payload) }, + /* 8 reserved bits */ + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[0]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[1]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[2]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[3]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[4]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[5]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[6]) }, + { RESERVED_BIT, offsetof(private_notify_payload_t, reserved[7]) }, + /* Length of the whole payload*/ + { PAYLOAD_LENGTH, offsetof(private_notify_payload_t, payload_length) }, + /* DOI as 32 bit field*/ + { U_INT_32, offsetof(private_notify_payload_t, doi) }, + /* Protocol ID as 8 bit field*/ + { U_INT_8, offsetof(private_notify_payload_t, protocol_id) }, + /* SPI Size as 8 bit field*/ + { SPI_SIZE, offsetof(private_notify_payload_t, spi_size) }, + /* Notify message type as 16 bit field*/ + { U_INT_16, offsetof(private_notify_payload_t, notify_type) }, + /* SPI as variable length field*/ + { SPI, offsetof(private_notify_payload_t, spi) }, + /* Key Exchange Data is from variable size */ + { CHUNK_DATA, offsetof(private_notify_payload_t, notify_data) }, +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Next Payload ! RESERVED ! Payload Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! DOI ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Protocol ID ! SPI Size ! Notify Message Type ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Security Parameter Index (SPI) ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! + ~ Notification Data ~ + ! ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + METHOD(payload_t, verify, status_t, private_notify_payload_t *this) @@ -331,7 +417,7 @@ METHOD(payload_t, verify, status_t, { case INVALID_KE_PAYLOAD: { - if (this->notification_data.len != 2) + if (this->type == NOTIFY && this->notify_data.len != 2) { bad_length = TRUE; } @@ -341,7 +427,7 @@ METHOD(payload_t, verify, status_t, case NAT_DETECTION_DESTINATION_IP: case ME_CONNECTAUTH: { - if (this->notification_data.len != HASH_SIZE_SHA1) + if (this->notify_data.len != HASH_SIZE_SHA1) { bad_length = TRUE; } @@ -351,7 +437,7 @@ METHOD(payload_t, verify, status_t, case INVALID_MAJOR_VERSION: case NO_PROPOSAL_CHOSEN: { - if (this->notification_data.len != 0) + if (this->type == NOTIFY && this->notify_data.len != 0) { bad_length = TRUE; } @@ -359,7 +445,7 @@ METHOD(payload_t, verify, status_t, } case ADDITIONAL_IP4_ADDRESS: { - if (this->notification_data.len != 4) + if (this->notify_data.len != 4) { bad_length = TRUE; } @@ -367,7 +453,7 @@ METHOD(payload_t, verify, status_t, } case ADDITIONAL_IP6_ADDRESS: { - if (this->notification_data.len != 16) + if (this->notify_data.len != 16) { bad_length = TRUE; } @@ -375,7 +461,7 @@ METHOD(payload_t, verify, status_t, } case AUTH_LIFETIME: { - if (this->notification_data.len != 4) + if (this->notify_data.len != 4) { bad_length = TRUE; } @@ -383,30 +469,37 @@ METHOD(payload_t, verify, status_t, } case IPCOMP_SUPPORTED: { - if (this->notification_data.len != 3) + if (this->notify_data.len != 3) { bad_length = TRUE; } break; } case ME_ENDPOINT: - if (this->notification_data.len != 8 && - this->notification_data.len != 12 && - this->notification_data.len != 24) + if (this->notify_data.len != 8 && + this->notify_data.len != 12 && + this->notify_data.len != 24) { bad_length = TRUE; } break; case ME_CONNECTID: - if (this->notification_data.len < 4 || - this->notification_data.len > 16) + if (this->notify_data.len < 4 || + this->notify_data.len > 16) { bad_length = TRUE; } break; case ME_CONNECTKEY: - if (this->notification_data.len < 16 || - this->notification_data.len > 32) + if (this->notify_data.len < 16 || + this->notify_data.len > 32) + { + bad_length = TRUE; + } + break; + case DPD_R_U_THERE: + case DPD_R_U_THERE_ACK: + if (this->notify_data.len != 4) { bad_length = TRUE; } @@ -419,23 +512,38 @@ METHOD(payload_t, verify, status_t, { DBG1(DBG_ENC, "invalid notify data length for %N (%d)", notify_type_names, this->notify_type, - this->notification_data.len); + this->notify_data.len); return FAILED; } return SUCCESS; } -METHOD(payload_t, get_encoding_rules, void, - private_notify_payload_t *this, encoding_rule_t **rules, size_t *rule_count) +METHOD(payload_t, get_encoding_rules, int, + private_notify_payload_t *this, encoding_rule_t **rules) +{ + if (this->type == NOTIFY) + { + *rules = encodings_v2; + return countof(encodings_v2); + } + *rules = encodings_v1; + return countof(encodings_v1); +} + +METHOD(payload_t, get_header_length, int, + private_notify_payload_t *this) { - *rules = notify_payload_encodings; - *rule_count = countof(notify_payload_encodings); + if (this->type == NOTIFY) + { + return 8 + this->spi_size; + } + return 12 + this->spi_size; } METHOD(payload_t, get_type, payload_type_t, private_notify_payload_t *this) { - return NOTIFY; + return this->type; } METHOD(payload_t, get_next_type, payload_type_t, @@ -453,19 +561,9 @@ METHOD(payload_t, set_next_type, void, /** * recompute the payloads length. */ -static void compute_length (private_notify_payload_t *this) +static void compute_length(private_notify_payload_t *this) { - size_t length = NOTIFY_PAYLOAD_HEADER_LENGTH; - - if (this->notification_data.ptr != NULL) - { - length += this->notification_data.len; - } - if (this->spi.ptr != NULL) - { - length += this->spi.len; - } - this->payload_length = length; + this->payload_length = get_header_length(this) + this->notify_data.len; } METHOD(payload_t, get_length, size_t, @@ -533,24 +631,55 @@ METHOD(notify_payload_t, set_spi, void, compute_length(this); } +METHOD(notify_payload_t, get_spi_data, chunk_t, + private_notify_payload_t *this) +{ + switch (this->protocol_id) + { + case PROTO_IKE: + if (this->spi.len == 16) + { + return this->spi; + } + default: + break; + } + return chunk_empty; +} + +METHOD(notify_payload_t, set_spi_data, void, + private_notify_payload_t *this, chunk_t spi) +{ + chunk_free(&this->spi); + switch (this->protocol_id) + { + case PROTO_IKE: + this->spi = chunk_clone(spi); + default: + break; + } + this->spi_size = this->spi.len; + compute_length(this); +} + METHOD(notify_payload_t, get_notification_data, chunk_t, private_notify_payload_t *this) { - return this->notification_data; + return this->notify_data; } METHOD(notify_payload_t, set_notification_data, void, private_notify_payload_t *this, chunk_t data) { - free(this->notification_data.ptr); - this->notification_data = chunk_clone(data); + free(this->notify_data.ptr); + this->notify_data = chunk_clone(data); compute_length(this); } METHOD2(payload_t, notify_payload_t, destroy, void, private_notify_payload_t *this) { - free(this->notification_data.ptr); + free(this->notify_data.ptr); free(this->spi.ptr); free(this); } @@ -558,7 +687,7 @@ METHOD2(payload_t, notify_payload_t, destroy, void, /* * Described in header */ -notify_payload_t *notify_payload_create() +notify_payload_t *notify_payload_create(payload_type_t type) { private_notify_payload_t *this; @@ -567,6 +696,7 @@ notify_payload_t *notify_payload_create() .payload_interface = { .verify = _verify, .get_encoding_rules = _get_encoding_rules, + .get_header_length = _get_header_length, .get_length = _get_length, .get_next_type = _get_next_type, .set_next_type = _set_next_type, @@ -579,13 +709,17 @@ notify_payload_t *notify_payload_create() .set_notify_type = _set_notify_type, .get_spi = _get_spi, .set_spi = _set_spi, + .get_spi_data = _get_spi_data, + .set_spi_data = _set_spi_data, .get_notification_data = _get_notification_data, .set_notification_data = _set_notification_data, .destroy = _destroy, }, + .doi = IKEV1_DOI_IPSEC, .next_payload = NO_PAYLOAD, - .payload_length = NOTIFY_PAYLOAD_HEADER_LENGTH, + .type = type, ); + compute_length(this); return &this->public; } @@ -593,12 +727,12 @@ notify_payload_t *notify_payload_create() * Described in header. */ notify_payload_t *notify_payload_create_from_protocol_and_type( - protocol_id_t protocol_id, notify_type_t notify_type) + payload_type_t type, protocol_id_t protocol, notify_type_t notify) { - notify_payload_t *notify = notify_payload_create(); + notify_payload_t *this = notify_payload_create(type); - notify->set_notify_type(notify, notify_type); - notify->set_protocol_id(notify, protocol_id); + this->set_notify_type(this, notify); + this->set_protocol_id(this, protocol); - return notify; + return this; } |