aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon/sa
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2015-04-22 14:34:53 +0200
committerTobias Brunner <tobias@strongswan.org>2016-03-04 16:02:58 +0100
commit2beb26b9489b0d94d2c1be3022099aa8bd02735c (patch)
treecc1c86d3ef9204619d05991ebbdc9695af873377 /src/libcharon/sa
parentfa5cfbdcbfdda3417a6d963c7d69c41746240dc4 (diff)
downloadstrongswan-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.c154
-rw-r--r--src/libcharon/sa/redirect_manager.h19
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_ @}*/