diff options
author | Tobias Brunner <tobias@strongswan.org> | 2015-04-22 14:34:53 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2016-03-04 16:02:58 +0100 |
commit | 2beb26b9489b0d94d2c1be3022099aa8bd02735c (patch) | |
tree | cc1c86d3ef9204619d05991ebbdc9695af873377 /src/libcharon/sa | |
parent | fa5cfbdcbfdda3417a6d963c7d69c41746240dc4 (diff) | |
download | strongswan-2beb26b9489b0d94d2c1be3022099aa8bd02735c.tar.bz2 strongswan-2beb26b9489b0d94d2c1be3022099aa8bd02735c.tar.xz |
redirect-manager: Add helper function to create and parse REDIRECT notify data
The same encoding is also used for the REDIRECT_FROM notifies.
Diffstat (limited to 'src/libcharon/sa')
-rw-r--r-- | src/libcharon/sa/redirect_manager.c | 154 | ||||
-rw-r--r-- | src/libcharon/sa/redirect_manager.h | 19 |
2 files changed, 162 insertions, 11 deletions
diff --git a/src/libcharon/sa/redirect_manager.c b/src/libcharon/sa/redirect_manager.c index e37c26f0d..ff92ac29f 100644 --- a/src/libcharon/sa/redirect_manager.c +++ b/src/libcharon/sa/redirect_manager.c @@ -17,6 +17,8 @@ #include <collections/linked_list.h> #include <threading/rwlock.h> +#include <bio/bio_reader.h> +#include <bio/bio_writer.h> typedef struct private_redirect_manager_t private_redirect_manager_t; @@ -41,6 +43,57 @@ struct private_redirect_manager_t { rwlock_t *lock; }; + +/** + * Gateway identify types + * + * The encoding is the same as that for corresponding ID payloads. + */ +typedef enum { + /** IPv4 address of the VPN gateway */ + GATEWAY_ID_TYPE_IPV4 = 1, + /** IPv6 address of the VPN gateway */ + GATEWAY_ID_TYPE_IPV6 = 2, + /** FQDN of the VPN gateway */ + GATEWAY_ID_TYPE_FQDN = 3, +} gateway_id_type_t; + +/** + * Mapping of gateway identity types to identity types + */ +static id_type_t gateway_to_id_type(gateway_id_type_t type) +{ + switch (type) + { + case GATEWAY_ID_TYPE_IPV4: + return ID_IPV4_ADDR; + case GATEWAY_ID_TYPE_IPV6: + return ID_IPV6_ADDR; + case GATEWAY_ID_TYPE_FQDN: + return ID_FQDN; + default: + return 0; + } +} + +/** + * Mapping of identity types to gateway identity types + */ +static gateway_id_type_t id_type_to_gateway(id_type_t type) +{ + switch (type) + { + case ID_IPV4_ADDR: + return GATEWAY_ID_TYPE_IPV4; + case ID_IPV6_ADDR: + return GATEWAY_ID_TYPE_IPV6; + case ID_FQDN: + return GATEWAY_ID_TYPE_FQDN; + default: + return 0; + } +} + METHOD(redirect_manager_t, add_provider, void, private_redirect_manager_t *this, redirect_provider_t *provider) { @@ -75,19 +128,16 @@ static bool should_redirect(private_redirect_manager_t *this, ike_sa_t *ike_sa, bool (**method)(void*,ike_sa_t*,identification_t**) = provider + offset; if (*method && (*method)(provider, ike_sa, gateway)) { - switch (*gateway ? (*gateway)->get_type(*gateway) : 0) + if (*gateway && id_type_to_gateway((*gateway)->get_type(*gateway))) { - case ID_IPV4_ADDR: - case ID_IPV6_ADDR: - case ID_FQDN: - redirect = TRUE; - break; - default: - DBG1(DBG_CFG, "redirect provider returned invalid gateway"); - DESTROY_IF(*gateway); - continue; + redirect = TRUE; + break; + } + else + { + DBG1(DBG_CFG, "redirect provider returned invalid gateway ID"); + DESTROY_IF(*gateway); } - break; } } enumerator->destroy(enumerator); @@ -140,3 +190,85 @@ redirect_manager_t *redirect_manager_create() return &this->public; } + +/* + * Encoding of a REDIRECT or REDIRECTED_FROM notify + * + 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 |C| RESERVED | Payload Length | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |Protocol ID(=0)| SPI Size (=0) | Notify Message Type | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | GW Ident Type | GW Ident Len | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ~ + ~ New Responder GW Identity ~ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | | + ~ Nonce Data ~ + | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + +/* + * Described in header + */ +chunk_t redirect_data_create(identification_t *gw, chunk_t nonce) +{ + gateway_id_type_t type; + bio_writer_t *writer; + chunk_t data; + + type = id_type_to_gateway(gw->get_type(gw)); + if (!type) + { + return chunk_empty; + } + + writer = bio_writer_create(0); + writer->write_uint8(writer, type); + writer->write_data8(writer, gw->get_encoding(gw)); + if (nonce.ptr) + { + writer->write_data(writer, nonce); + } + + data = writer->extract_buf(writer); + writer->destroy(writer); + return data; +} + +/* + * Described in header + */ +identification_t *redirect_data_parse(chunk_t data, chunk_t *nonce) +{ + bio_reader_t *reader; + id_type_t id_type; + chunk_t gateway; + u_int8_t type; + + reader = bio_reader_create(data); + if (!reader->read_uint8(reader, &type) || + !reader->read_data8(reader, &gateway)) + { + DBG1(DBG_ENC, "invalid REDIRECT notify data"); + reader->destroy(reader); + return NULL; + } + id_type = gateway_to_id_type(type); + if (!id_type) + { + DBG1(DBG_ENC, "invalid gateway ID type (%d) in REDIRECT notify", type); + reader->destroy(reader); + return NULL; + } + if (nonce) + { + *nonce = chunk_clone(reader->peek(reader)); + } + reader->destroy(reader); + return identification_create_from_encoding(id_type, gateway); +} diff --git a/src/libcharon/sa/redirect_manager.h b/src/libcharon/sa/redirect_manager.h index a74cfa3b4..45a727c29 100644 --- a/src/libcharon/sa/redirect_manager.h +++ b/src/libcharon/sa/redirect_manager.h @@ -87,4 +87,23 @@ struct redirect_manager_t { */ redirect_manager_t *redirect_manager_create(); +/** + * Create notification data of a REDIRECT or REDIRECT_FROM payload using the + * given gateway identity and optional nonce (only used during IKE_SA_INIT). + * + * @param gw gateway identity (IP or FQDN), gets cloned + * @param nonce nonce value, or chunk_empty, gets cloned + * @return notify data, chunk_empty if ID type is not supported + */ +chunk_t redirect_data_create(identification_t *gw, chunk_t nonce); + +/** + * Parse notification data of a REDIRECT or REDIRECTED_FROM notify payload. + * + * @param data notification data to parse + * @param nonce[out] nonce data (allocated), if any was provided + * @return gateway identity, NULL if data is invalid + */ +identification_t *redirect_data_parse(chunk_t data, chunk_t *nonce); + #endif /** REDIRECT_MANAGER_H_ @}*/ |