[strongSwan-dev] [PATCH 4/5] ikev1: Add keyword onlycerts for parameter fragmentation

Volker Rümelin vr_strongswan at t-online.de
Mon Mar 10 22:36:43 CET 2014


It seems Windows 7 peers only accept proprietary fragmented messages
if they expect certificates. With fragmentation = onlycerts Stongswan
only sends fragmented messages if the peer supports it and the message
contains certificates.
---
 man/ipsec.conf.5.in                      | 14 +++++---
 src/libcharon/config/ike_cfg.h           |  3 ++
 src/libcharon/sa/ikev1/task_manager_v1.c | 59 +++++++++++++++++++++++++-------
 src/starter/args.c                       |  1 +
 src/starter/confread.h                   |  1 +
 5 files changed, 61 insertions(+), 17 deletions(-)

diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in
index a0be755..64dbc89 100644
--- a/man/ipsec.conf.5.in
+++ b/man/ipsec.conf.5.in
@@ -445,20 +445,24 @@ force UDP encapsulation for ESP packets even if no NAT situation is detected.
 This may help to surmount restrictive firewalls. In order to force the peer to
 encapsulate packets, NAT detection payloads are faked.
 .TP
-.BR fragmentation " = yes | force | " no
+.BR fragmentation " = yes | force | onlycerts | " no
 whether to use IKE fragmentation (proprietary IKEv1 extension).  Acceptable
 values are
-.BR yes ,
-.B force
+.BR yes,
+.B force,
+.B onlycerts
 and
 .B no
 (the default). Fragmented messages sent by a peer are always accepted
 irrespective of the value of this option. If set to
-.BR yes ,
+.BR yes,
 and the peer supports it, larger IKE messages will be sent in fragments.
 If set to
 .B force
-the initial IKE message will already be fragmented if required.
+the initial IKE message will already be fragmented if required. If set to
+.B onlycerts,
+and the peer supports it, only larger IKE messages containing certificates will
+be sent in fragments.
 .TP
 .BR ike " = <cipher suites>"
 comma-separated list of IKE/ISAKMP SA encryption/authentication algorithms
diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h
index f9e4fbe..a3a3939 100644
--- a/src/libcharon/config/ike_cfg.h
+++ b/src/libcharon/config/ike_cfg.h
@@ -56,6 +56,9 @@ enum fragmentation_t {
 	FRAGMENTATION_YES,
 	/** force use of fragmentation (even for the first message) */
 	FRAGMENTATION_FORCE,
+	/** enable fragmentation if supported by peer and message contains at least
+		one certificate */
+	FRAGMENTATION_ONLYCERTS,
 };
 
 /**
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index 7e5b08d..e097032 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -14,6 +14,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (c) 2013 Volker Rümelin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include "task_manager_v1.h"
 
 #include <math.h>
@@ -404,13 +426,17 @@ static bool send_fragment(private_task_manager_t *this, bool request,
 }
 
 /**
- * Get the packet fragment size. A fragment size of 0 disables fragmentation.
+ * Generate message and set packet fragment size. A fragment size of 0 disables
+ * fragmentation.
  */
-static size_t get_fragsize(private_task_manager_t *this, packet_t *packet)
+static status_t generate_message(private_task_manager_t *this,
+								 message_t *message, packet_t **packet)
 {
 	bool use_frags = FALSE;
 	ike_cfg_t *ike_cfg;
 	size_t frag_size = 0;
+	payload_t *cert;
+	status_t status;
 
 	ike_cfg = this->ike_sa->get_ike_cfg(this->ike_sa);
 	if (ike_cfg)
@@ -424,6 +450,12 @@ static size_t get_fragsize(private_task_manager_t *this, packet_t *packet)
 				use_frags = this->ike_sa->supports_extension(this->ike_sa,
 														EXT_IKE_FRAGMENTATION);
 				break;
+			case FRAGMENTATION_ONLYCERTS:
+				cert = message->get_payload(message, CERTIFICATE_V1);
+				use_frags = cert != NULL &&
+							this->ike_sa->supports_extension(this->ike_sa,
+														EXT_IKE_FRAGMENTATION);
+				break;
 			default:
 				break;
 		}
@@ -433,8 +465,8 @@ static size_t get_fragsize(private_task_manager_t *this, packet_t *packet)
 	{
 		host_t *src, *dst;
 
-		src = packet->get_source(packet);
-		dst = packet->get_destination(packet);
+		src = message->get_source(message);
+		dst = message->get_destination(message);
 
 		frag_size = this->frag.size;
 		if (dst->get_port(dst) != IKEV2_UDP_PORT &&
@@ -445,7 +477,13 @@ static size_t get_fragsize(private_task_manager_t *this, packet_t *packet)
 		}
 	}
 
-	return frag_size;
+	status = this->ike_sa->generate_message(this->ike_sa, message, packet);
+	if (status == SUCCESS)
+	{
+		(*packet)->set_fragsize(*packet, frag_size);
+	}
+
+	return status;
 }
 
 /**
@@ -458,7 +496,7 @@ static bool send_packet(private_task_manager_t *this, bool request,
 	size_t frag_size;
 
 	data = packet->get_data(packet);
-	frag_size = get_fragsize(this, packet);
+	frag_size = packet->get_fragsize(packet);
 	if (frag_size > 0 && data.len > frag_size)
 	{
 		fragment_payload_t *fragment;
@@ -814,8 +852,7 @@ METHOD(task_manager_t, initiate, status_t,
 	}
 
 	DESTROY_IF(this->initiating.packet);
-	status = this->ike_sa->generate_message(this->ike_sa, message,
-											&this->initiating.packet);
+	status = generate_message(this, message, &this->initiating.packet);
 	if (status != SUCCESS)
 	{
 		/* message generation failed. There is nothing more to do than to
@@ -930,8 +967,7 @@ static status_t build_response(private_task_manager_t *this, message_t *request)
 		message->destroy(message);
 		return initiate(this);
 	}
-	status = this->ike_sa->generate_message(this->ike_sa, message,
-											&this->responding.packet);
+	status = generate_message(this, message, &this->responding.packet);
 	message->destroy(message);
 	if (status != SUCCESS)
 	{
@@ -996,8 +1032,7 @@ static void send_notify(private_task_manager_t *this, message_t *request,
 	}
 	response->set_source(response, me->clone(me));
 	response->set_destination(response, other->clone(other));
-	if (this->ike_sa->generate_message(this->ike_sa, response,
-									   &packet) == SUCCESS)
+	if (generate_message(this, response, &packet) == SUCCESS)
 	{
 		send_packet(this, TRUE, packet);
 	}
diff --git a/src/starter/args.c b/src/starter/args.c
index f5a617e..936ca60 100644
--- a/src/starter/args.c
+++ b/src/starter/args.c
@@ -113,6 +113,7 @@ static const char *LST_fragmentation[] = {
 	"no",
 	"yes",
 	"force",
+	"onlycerts",
 	 NULL
 };
 
diff --git a/src/starter/confread.h b/src/starter/confread.h
index d55a17e..ffb4a59 100644
--- a/src/starter/confread.h
+++ b/src/starter/confread.h
@@ -74,6 +74,7 @@ typedef enum {
 		FRAGMENTATION_NO,
 		FRAGMENTATION_YES,
 		FRAGMENTATION_FORCE,
+		FRAGMENTATION_ONLYCERTS,
 } fragmentation_t;
 
 typedef enum {
-- 
1.8.4.5




More information about the Dev mailing list