diff options
-rw-r--r-- | debian/patches/1006-vici-add-deprecated-async-parameter.patch | 49 | ||||
-rw-r--r-- | debian/patches/1007-support-gre-key-in-ikev1.patch | 508 |
2 files changed, 557 insertions, 0 deletions
diff --git a/debian/patches/1006-vici-add-deprecated-async-parameter.patch b/debian/patches/1006-vici-add-deprecated-async-parameter.patch new file mode 100644 index 000000000..90ae658d4 --- /dev/null +++ b/debian/patches/1006-vici-add-deprecated-async-parameter.patch @@ -0,0 +1,49 @@ +From 0c33419af4403597aac1f75e8d044150ecc2f03c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> +Date: Mon, 21 Sep 2015 13:42:15 +0300 +Subject: [PATCH] vici: add (deprecated) async parameter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This is obsoleted by the new "timeout=-1" option that achieves +the same. Only for compatibility with old versions of quagga-nhrp. + +Signed-off-by: Timo Teräs <timo.teras@iki.fi> +--- + src/libcharon/plugins/vici/vici_control.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c +index 9c6b86741..718d14b3c 100644 +--- a/src/libcharon/plugins/vici/vici_control.c ++++ b/src/libcharon/plugins/vici/vici_control.c +@@ -197,7 +197,7 @@ CALLBACK(initiate, vici_message_t*, + host_t *my_host = NULL, *other_host = NULL; + char *child, *ike, *my_host_str, *other_host_str; + int timeout; +- bool limits; ++ bool limits, async; + controller_cb_t log_cb = NULL; + log_info_t log = { + .dispatcher = this->dispatcher, +@@ -208,6 +208,7 @@ CALLBACK(initiate, vici_message_t*, + ike = request->get_str(request, NULL, "ike"); + timeout = request->get_int(request, 0, "timeout"); + limits = request->get_bool(request, FALSE, "init-limits"); ++ async = request->get_bool(request, FALSE, "async"); + log.level = request->get_int(request, 1, "loglevel"); + my_host_str = request->get_str(request, NULL, "my-host"); + other_host_str = request->get_str(request, NULL, "other-host"); +@@ -216,7 +217,7 @@ CALLBACK(initiate, vici_message_t*, + { + return send_reply(this, "missing configuration name"); + } +- if (timeout >= 0) ++ if (timeout >= 0 && !async) + { + log_cb = (controller_cb_t)log_vici; + } +-- +2.20.1 + diff --git a/debian/patches/1007-support-gre-key-in-ikev1.patch b/debian/patches/1007-support-gre-key-in-ikev1.patch new file mode 100644 index 000000000..5b9d0d184 --- /dev/null +++ b/debian/patches/1007-support-gre-key-in-ikev1.patch @@ -0,0 +1,508 @@ +From 0f09d2cb000f9037a2b73ff5caa797b4caee492a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timo=20Ter=C3=A4s?= <timo.teras@iki.fi> +Date: Mon, 21 Sep 2015 13:42:18 +0300 +Subject: [PATCH] support gre key in ikev1 + +this implements gre key negotiation in ikev1 similarly to the +ipsec-tools patch in alpine. + +the from/to port pair is internally used as gre key for gre +protocol traffic selectors. since from/to pairs 0/0xffff and +0xffff/0 have special meaning, the gre keys 0xffff and 0xffff0000 +will not work. + +this is not standard compliant, and should probably not be upstreamed +or used widely, but it is applied for interoperability with alpine +racoon for the time being. +--- + src/libcharon/encoding/payloads/id_payload.c | 68 ++++++++++++++----- + src/libcharon/encoding/payloads/id_payload.h | 6 +- + .../kernel_netlink/kernel_netlink_ipsec.c | 40 ++++++++--- + src/libcharon/plugins/stroke/stroke_config.c | 5 ++ + src/libcharon/plugins/unity/unity_narrow.c | 2 +- + src/libcharon/plugins/vici/vici_config.c | 9 ++- + src/libcharon/sa/ikev1/tasks/quick_mode.c | 16 +++-- + .../selectors/traffic_selector.c | 34 +++++++++- + .../selectors/traffic_selector.h | 31 +++++++++ + 9 files changed, 171 insertions(+), 40 deletions(-) + +diff --git a/src/libcharon/encoding/payloads/id_payload.c b/src/libcharon/encoding/payloads/id_payload.c +index b2f1adbbc..6b44d0cf6 100644 +--- a/src/libcharon/encoding/payloads/id_payload.c ++++ b/src/libcharon/encoding/payloads/id_payload.c +@@ -245,18 +245,20 @@ METHOD(id_payload_t, get_identification, identification_t*, + * Create a traffic selector from an range ID + */ + static traffic_selector_t *get_ts_from_range(private_id_payload_t *this, +- ts_type_t type) ++ ts_type_t type, ++ uint16_t from_port, uint16_t to_port) + { + return traffic_selector_create_from_bytes(this->protocol_id, type, +- chunk_create(this->id_data.ptr, this->id_data.len / 2), this->port, +- chunk_skip(this->id_data, this->id_data.len / 2), this->port ?: 65535); ++ chunk_create(this->id_data.ptr, this->id_data.len / 2), from_port, ++ chunk_skip(this->id_data, this->id_data.len / 2), to_port); + } + + /** + * Create a traffic selector from an subnet ID + */ + static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this, +- ts_type_t type) ++ ts_type_t type, ++ uint16_t from_port, uint16_t to_port) + { + traffic_selector_t *ts; + chunk_t net, netmask; +@@ -269,7 +271,7 @@ static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this, + netmask.ptr[i] = (netmask.ptr[i] ^ 0xFF) | net.ptr[i]; + } + ts = traffic_selector_create_from_bytes(this->protocol_id, type, +- net, this->port, netmask, this->port ?: 65535); ++ net, from_port, netmask, to_port); + chunk_free(&netmask); + return ts; + } +@@ -278,51 +280,76 @@ static traffic_selector_t *get_ts_from_subnet(private_id_payload_t *this, + * Create a traffic selector from an IP ID + */ + static traffic_selector_t *get_ts_from_ip(private_id_payload_t *this, +- ts_type_t type) ++ ts_type_t type, ++ uint16_t from_port, uint16_t to_port) + { + return traffic_selector_create_from_bytes(this->protocol_id, type, +- this->id_data, this->port, this->id_data, this->port ?: 65535); ++ this->id_data, from_port, this->id_data, to_port); + } + + METHOD(id_payload_t, get_ts, traffic_selector_t*, +- private_id_payload_t *this) ++ private_id_payload_t *this, id_payload_t *other_, bool initiator) + { ++ private_id_payload_t *other = (private_id_payload_t *) other_; ++ uint16_t from_port, to_port; ++ ++ if (other && this->protocol_id == IPPROTO_GRE && other->protocol_id == IPPROTO_GRE) ++ { ++ if (initiator) ++ { ++ from_port = this->port; ++ to_port = other->port; ++ } ++ else ++ { ++ from_port = other->port; ++ to_port = this->port; ++ } ++ if (from_port == 0 && to_port == 0) ++ to_port = 0xffff; ++ } ++ else ++ { ++ from_port = this->port; ++ to_port = this->port ?: 0xffff; ++ } ++ + switch (this->id_type) + { + case ID_IPV4_ADDR_SUBNET: + if (this->id_data.len == 8) + { +- return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE); ++ return get_ts_from_subnet(this, TS_IPV4_ADDR_RANGE, from_port, to_port); + } + break; + case ID_IPV6_ADDR_SUBNET: + if (this->id_data.len == 32) + { +- return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE); ++ return get_ts_from_subnet(this, TS_IPV6_ADDR_RANGE, from_port, to_port); + } + break; + case ID_IPV4_ADDR_RANGE: + if (this->id_data.len == 8) + { +- return get_ts_from_range(this, TS_IPV4_ADDR_RANGE); ++ return get_ts_from_range(this, TS_IPV4_ADDR_RANGE, from_port, to_port); + } + break; + case ID_IPV6_ADDR_RANGE: + if (this->id_data.len == 32) + { +- return get_ts_from_range(this, TS_IPV6_ADDR_RANGE); ++ return get_ts_from_range(this, TS_IPV6_ADDR_RANGE, from_port, to_port); + } + break; + case ID_IPV4_ADDR: + if (this->id_data.len == 4) + { +- return get_ts_from_ip(this, TS_IPV4_ADDR_RANGE); ++ return get_ts_from_ip(this, TS_IPV4_ADDR_RANGE, from_port, to_port); + } + break; + case ID_IPV6_ADDR: + if (this->id_data.len == 16) + { +- return get_ts_from_ip(this, TS_IPV6_ADDR_RANGE); ++ return get_ts_from_ip(this, TS_IPV6_ADDR_RANGE, from_port, to_port); + } + break; + default: +@@ -397,7 +424,7 @@ id_payload_t *id_payload_create_from_identification(payload_type_t type, + /* + * Described in header. + */ +-id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts) ++id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts, bool initiator) + { + private_id_payload_t *this; + uint8_t mask; +@@ -460,8 +487,17 @@ id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts) + ts->get_from_address(ts), ts->get_to_address(ts)); + net->destroy(net); + } +- this->port = ts->get_from_port(ts); + this->protocol_id = ts->get_protocol(ts); ++ if (initiator || this->protocol_id != IPPROTO_GRE) ++ { ++ this->port = ts->get_from_port(ts); ++ } ++ else ++ { ++ this->port = ts->get_to_port(ts); ++ if (this->port == 0xffff && ts->get_from_port(ts) == 0) ++ this->port = 0; ++ } + this->payload_length += this->id_data.len; + + return &this->public; +diff --git a/src/libcharon/encoding/payloads/id_payload.h b/src/libcharon/encoding/payloads/id_payload.h +index 283780624..fafeca8bc 100644 +--- a/src/libcharon/encoding/payloads/id_payload.h ++++ b/src/libcharon/encoding/payloads/id_payload.h +@@ -48,11 +48,11 @@ struct id_payload_t { + identification_t *(*get_identification) (id_payload_t *this); + + /** +- * Creates a traffic selector form a ID_ADDR_SUBNET/RANGE identity. ++ * Creates a traffic selector form a ID_ADDR_SUBNET/RANGE identity pair. + * + * @return traffic selector, NULL on failure + */ +- traffic_selector_t* (*get_ts)(id_payload_t *this); ++ traffic_selector_t* (*get_ts)(id_payload_t *this, id_payload_t *other, bool initiator); + + /** + * Get encoded payload without fixed payload header (used for IKEv1). +@@ -91,6 +91,6 @@ id_payload_t *id_payload_create_from_identification(payload_type_t type, + * @param ts traffic selector + * @return PLV1_ID id_paylad_t object. + */ +-id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts); ++id_payload_t *id_payload_create_from_ts(traffic_selector_t *ts, bool initiator); + + #endif /** ID_PAYLOAD_H_ @}*/ +diff --git a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c +index 40fff7e05..0743f7a95 100644 +--- a/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c ++++ b/src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c +@@ -869,7 +869,18 @@ static struct xfrm_selector ts2selector(traffic_selector_t *src, + ts2subnet(src, &sel.saddr, &sel.prefixlen_s); + ts2ports(dst, &sel.dport, &sel.dport_mask); + ts2ports(src, &sel.sport, &sel.sport_mask); +- if ((sel.proto == IPPROTO_ICMP || sel.proto == IPPROTO_ICMPV6) && ++ if (sel.proto == IPPROTO_GRE) ++ { ++ sel.sport = htons(src->get_from_port(src)); ++ sel.dport = htons(src->get_to_port(src)); ++ sel.sport_mask = ~0; ++ sel.dport_mask = ~0; ++ if (sel.sport == htons(0) && sel.dport == htons(0xffff)) ++ { ++ sel.sport = sel.dport = sel.sport_mask = sel.dport_mask = 0; ++ } ++ } ++ else if ((sel.proto == IPPROTO_ICMP || sel.proto == IPPROTO_ICMPV6) && + (sel.dport || sel.sport)) + { + /* the kernel expects the ICMP type and code in the source and +@@ -893,7 +904,7 @@ static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src) + { + u_char *addr; + uint8_t prefixlen; +- uint16_t port = 0; ++ uint16_t from_port = 0, to_port = 65535; + host_t *host = NULL; + + if (src) +@@ -902,7 +913,7 @@ static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src) + prefixlen = sel->prefixlen_s; + if (sel->sport_mask) + { +- port = ntohs(sel->sport); ++ from_port = to_port = ntohs(sel->sport); + } + } + else +@@ -911,14 +922,27 @@ static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src) + prefixlen = sel->prefixlen_d; + if (sel->dport_mask) + { +- port = ntohs(sel->dport); ++ from_port = to_port = ntohs(sel->dport); ++ } ++ } ++ if (sel->proto == IPPROTO_GRE) ++ { ++ if (sel->sport_mask) ++ { ++ from_port = ntohs(sel->sport); ++ to_port = ntohs(sel->dport); ++ } ++ else ++ { ++ from_port = 0; ++ to_port = 0xffff; + } + } +- if (sel->proto == IPPROTO_ICMP || sel->proto == IPPROTO_ICMPV6) ++ else if (sel->proto == IPPROTO_ICMP || sel->proto == IPPROTO_ICMPV6) + { /* convert ICMP[v6] message type and code as supplied by the kernel in + * source and destination ports (both in network order) */ +- port = (sel->sport >> 8) | (sel->dport & 0xff00); +- port = ntohs(port); ++ from_port = (sel->sport >> 8) | (sel->dport & 0xff00); ++ from_port = to_port = ntohs(from_port); + } + /* The Linux 2.6 kernel does not set the selector's family field, + * so as a kludge we additionally test the prefix length. +@@ -935,7 +959,7 @@ static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src) + if (host) + { + return traffic_selector_create_from_subnet(host, prefixlen, +- sel->proto, port, port ?: 65535); ++ sel->proto, from_port, to_port); + } + return NULL; + } +diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c +index 8cdb5ef48..a81949c09 100644 +--- a/src/libcharon/plugins/stroke/stroke_config.c ++++ b/src/libcharon/plugins/stroke/stroke_config.c +@@ -936,6 +936,11 @@ static bool parse_protoport(char *token, uint16_t *from_port, + *from_port = 0xffff; + *to_port = 0; + } ++ else if (*port && *protocol == IPPROTO_GRE) ++ { ++ p = strtol(port, &endptr, 0); ++ traffic_selector_split_grekey(p, from_port, to_port); ++ } + else if (*port) + { + svc = getservbyname(port, NULL); +diff --git a/src/libcharon/plugins/unity/unity_narrow.c b/src/libcharon/plugins/unity/unity_narrow.c +index afbd6cc7e..911fe70c6 100644 +--- a/src/libcharon/plugins/unity/unity_narrow.c ++++ b/src/libcharon/plugins/unity/unity_narrow.c +@@ -248,7 +248,7 @@ METHOD(listener_t, message, bool, + if (!first) + { + id_payload = (id_payload_t*)payload; +- tsr = id_payload->get_ts(id_payload); ++ tsr = id_payload->get_ts(id_payload, NULL, FALSE); + break; + } + first = FALSE; +diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c +index f0fd8a989..9f9dcfa45 100644 +--- a/src/libcharon/plugins/vici/vici_config.c ++++ b/src/libcharon/plugins/vici/vici_config.c +@@ -691,8 +691,13 @@ CALLBACK(parse_ts, bool, + } + else if (*port && !streq(port, "any")) + { +- svc = getservbyname(port, NULL); +- if (svc) ++ if (proto == IPPROTO_GRE) ++ { ++ p = strtol(port, &end, 0); ++ if (*end) return FALSE; ++ traffic_selector_split_grekey(p, &from, &to); ++ } ++ else if ((svc = getservbyname(port, NULL)) != NULL) + { + from = to = ntohs(svc->s_port); + } +diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c +index b0a42b8bd..4ef4bf324 100644 +--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c ++++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c +@@ -567,9 +567,9 @@ static void add_ts(private_quick_mode_t *this, message_t *message) + { + id_payload_t *id_payload; + +- id_payload = id_payload_create_from_ts(this->tsi); ++ id_payload = id_payload_create_from_ts(this->tsi, TRUE); + message->add_payload(message, &id_payload->payload_interface); +- id_payload = id_payload_create_from_ts(this->tsr); ++ id_payload = id_payload_create_from_ts(this->tsr, FALSE); + message->add_payload(message, &id_payload->payload_interface); + } + +@@ -580,7 +580,7 @@ static bool get_ts(private_quick_mode_t *this, message_t *message) + { + traffic_selector_t *tsi = NULL, *tsr = NULL; + enumerator_t *enumerator; +- id_payload_t *id_payload; ++ id_payload_t *idi = NULL, *idr = NULL; + payload_t *payload; + host_t *hsi, *hsr; + bool first = TRUE; +@@ -590,20 +590,22 @@ static bool get_ts(private_quick_mode_t *this, message_t *message) + { + if (payload->get_type(payload) == PLV1_ID) + { +- id_payload = (id_payload_t*)payload; +- + if (first) + { +- tsi = id_payload->get_ts(id_payload); ++ idi = (id_payload_t*)payload; + first = FALSE; + } + else + { +- tsr = id_payload->get_ts(id_payload); ++ idr = (id_payload_t*)payload; + break; + } + } + } ++ if (idi && idr) { ++ tsi = idi->get_ts(idi, idr, TRUE); ++ tsr = idr->get_ts(idr, idi, FALSE); ++ } + enumerator->destroy(enumerator); + + /* create host2host selectors if ID payloads missing */ +diff --git a/src/libstrongswan/selectors/traffic_selector.c b/src/libstrongswan/selectors/traffic_selector.c +index cfd2b029d..0b9697d5e 100644 +--- a/src/libstrongswan/selectors/traffic_selector.c ++++ b/src/libstrongswan/selectors/traffic_selector.c +@@ -198,6 +198,14 @@ static int print_icmp(printf_hook_data_t *data, uint16_t port) + return print_in_hook(data, "%d", type); + } + ++/** ++ * Print GRE key ++ */ ++static int print_grekey(printf_hook_data_t *data, uint16_t from_port, uint16_t to_port) ++{ ++ return print_in_hook(data, "%d", traffic_selector_grekey(from_port, to_port)); ++} ++ + /** + * Described in header. + */ +@@ -302,8 +310,11 @@ int traffic_selector_printf_hook(printf_hook_data_t *data, + if (has_ports) + { + written += print_in_hook(data, "/"); +- +- if (this->from_port == this->to_port) ++ if (this->protocol == IPPROTO_GRE) ++ { ++ written += print_grekey(data, this->from_port, this->to_port); ++ } ++ else if (this->from_port == this->to_port) + { + struct servent *serv; + +@@ -377,7 +388,24 @@ METHOD(traffic_selector_t, get_subset, traffic_selector_t*, + /* select protocol, which is not zero */ + protocol = max(this->protocol, other->protocol); + +- if ((is_opaque(this) && is_opaque(other)) || ++ if (this->protocol == IPPROTO_GRE) ++ { ++ if (is_any(this)) ++ { ++ from_port = other->from_port; ++ to_port = other->to_port; ++ } ++ else if (is_any(other) || ++ (this->from_port == other->from_port && ++ this->to_port == other->to_port)) ++ { ++ from_port = this->from_port; ++ to_port = this->to_port; ++ } ++ else ++ return NULL; ++ } ++ else if ((is_opaque(this) && is_opaque(other)) || + (is_opaque(this) && is_any(other)) || + (is_opaque(other) && is_any(this))) + { +diff --git a/src/libstrongswan/selectors/traffic_selector.h b/src/libstrongswan/selectors/traffic_selector.h +index 03f7a6d8c..b27ca4ad1 100644 +--- a/src/libstrongswan/selectors/traffic_selector.h ++++ b/src/libstrongswan/selectors/traffic_selector.h +@@ -120,6 +120,9 @@ struct traffic_selector_t { + * 8 bits and the code in the least significant 8 bits. Use the utility + * functions to extract them. + * ++ * If the protocol is GRE, the high 16-bits of the 32-bit GRE key is stored ++ * in the from port. Use the utility function to merge and split them. ++ * + * @return port + */ + uint16_t (*get_from_port)(traffic_selector_t *this); +@@ -134,6 +137,9 @@ struct traffic_selector_t { + * 8 bits and the code in the least significant 8 bits. Use the utility + * functions to extract them. + * ++ * If the protocol is GRE, the low 16-bits of the 32-bit GRE key is stored ++ * in the to port. Use the utility function to merge and split them. ++ * + * @return port + */ + uint16_t (*get_to_port)(traffic_selector_t *this); +@@ -277,6 +283,31 @@ static inline uint8_t traffic_selector_icmp_code(uint16_t port) + int traffic_selector_cmp(traffic_selector_t *a, traffic_selector_t *b, + void *opts); + ++/** ++ * Reconstruct the 32-bit GRE KEY in host order from a from/to ports. ++ * ++ * @param from_port port number in host order ++ * @param to_port port number in host order ++ * @return GRE KEY in host order ++ */ ++static inline uint32_t traffic_selector_grekey(uint16_t from_port, uint16_t to_port) ++{ ++ return (from_port << 16) | to_port; ++} ++ ++/** ++ * Split 32-bit GRE KEY in host order to from/to ports. ++ * ++ * @param grekey grekey in host order ++ * @param from_port from port in host order ++ * @param to_port to port in host order ++ */ ++static inline void traffic_selector_split_grekey(uint32_t grekey, uint16_t *from_port, uint16_t *to_port) ++{ ++ *from_port = grekey >> 16; ++ *to_port = grekey & 0xffff; ++} ++ + /** + * Create a new traffic selector using human readable params. + * +-- +2.20.1 + |