[strongSwan] ipv6ready IKEv2_Self_Test v1.0.3 failing with strongSwan

Jiri Bohac jbohac at suse.cz
Fri Jul 23 17:46:22 CEST 2010


Hi,

just a few updates and clarificationsto my previous post...

On Tue, Jul 20, 2010 at 11:03:04PM +0200, Jiri Bohac wrote:

[...] 

> The current (and also mandated by USGv6) version of the test tool is 1.0.3.

Actually, not all of the tests are required by USGv6. I updated
the table below with a column saying which ones are:
	M = mandatory
	s = SHOULD
	S = SHOULD+

I also started debugging the individual tests. I found that the
linux-strongswan/ikev2.rmt remote script that comes with KOI has some deficiencies:
- the lifetimes specified by the test script are ignored
- the algorithms specified by the test script are ignored
I attach a new version of this script that attempts these issues.

However, it turns out, not all the algorithm problems can be
fixed by a remote script. The test scripts don't  specify which
algorithms should be put in a single proposal and which should be
put in separate proposals. This needs to be fixed in the ikev2
testsuite. See comment for test #28 below.

Also, probably most interesting to the strongSwan developers,
some tests cannot be passed by strongSwan, because there is no
way to specify which algorithms in a KMP proposal should be used
by used for PRF and which should be used for integrity. See
comment for test #30 below.


> The new v1.1.0 test specification has removed many of the test cases that
> I see failing in the 1.0.3 version (good! the ones I looked into fail for
> totally bogus reasons). I list all the failures below, the
> tests removed in v1.1.0 are marked with an asterisk:

	12 *	Test IKEv2.EN.I.1.1.3.4: Close Connection when receiving INITIAL_CONTACT
	13 *	Test IKEv2.EN.I.1.1.3.5: Sending Liveness check
	14	Test IKEv2.EN.I.1.1.3.6: Sending Delete Payload for IKE_SA
	15 *M	Test IKEv2.EN.I.1.1.3.7: Sending Delete Payload for CHILD_SA
		#  RFC 4306:
		#     "When an SA
		#      expires (based on locally configured values of either lifetime or
		#      octets passed), and implementation MAY either try to renew it with a
		#      CREATE_CHILD_SA exchange or it MAY delete (close) the old SA and
		#      create a new one.
		#   strongSwan seems to do neither, that's why it never sends the INFORMATIONAL
		#   message with the delete payload

	16 *	Test IKEv2.EN.I.1.1.3.8: Sending Liveness check with unprotected messages
	17	Test IKEv2.EN.I.1.1.4.1 Part A: Invalid payload type 1
	18	Test IKEv2.EN.I.1.1.4.1 Part B: Invalid payload type 32
	19	Test IKEv2.EN.I.1.1.4.1 Part C: Invalid payload type 49
	20	Test IKEv2.EN.I.1.1.4.1 Part D: Invalid payload type 255
	21	Test IKEv2.EN.I.1.1.4.2 Part A: Invalid payload type 1
	22	Test IKEv2.EN.I.1.1.4.2 Part B: Invalid payload type 32
	23	Test IKEv2.EN.I.1.1.4.2 Part C: Invalid payload type 49
	24	Test IKEv2.EN.I.1.1.4.2 Part D: Invalid payload type 255
	26	Test IKEv2.EN.I.1.1.5.2: Interaction of COOKIE and INVALID_KE_PAYLOAD
	27	Test IKEv2.EN.I.1.1.5.3: Interaction of COOKIE and INVALID_KE_PAYLOAD with unoptimized Responder
	28  M	Test IKEv2.EN.I.1.1.6.1 Part A: Encryption Algorithm ENCR_AES_CBC
		# works with my updated remote script that obeys the algorithms specified by the test script
		# this breaks e.g. I.1.1.6.4.A, which requires two proposals, not one proposal with two encr. transforms
		# Testsuite problem: when the test scripts configure two algorithms of the same kind (encryption/integrity/...) 
		# they don't specify whether they should be both added to a single proposal or whether multiple proposals
		# are to be created. This can not be fixed by the remote scripts themselves.

	29 *s	Test IKEv2.EN.I.1.1.6.1 Part B: Encryption Algorithm ENCR_AES_CTR
		#not supported; FIXME: kernel or strongSwan? ...

	30  S	Test IKEv2.EN.I.1.1.6.1 Part C: Pseudo-random Function PRF_AES128_XCBC
		# strongSwan can not currently pass this test; it wants to set PRF_HMAC_SHA1 as a PRF algorithm and
		#  AUTH_HMAC_SHA1_96 + AUTH_AES_XCBC_96 as integrity algorithms.
		#  However, strongSwan automatically uses any integrity algorithm specified in a ike= prposal definition
		#  see src/libcharon/config/proposal.c: add_string_algo()
		#  for both integrity and PRF. Result: "NG PRF:	(received:PRF_AES128_XCBC, PRF_HMAC_SHA1, expected:PRF_HMAC_SHA1)"

	31  S	Test IKEv2.EN.I.1.1.6.1 Part D: Integrity Algorithm AUTH_AES_XCBC_96
		# same  as #30

	32  M	Test IKEv2.EN.I.1.1.6.1 Part E: D-H Group Group 14
		# works now with updated remote script, see #28
		
	33  M	Test IKEv2.EN.I.1.1.6.2 Part A: Encryption Algorithm ENCR_AES_CBC
		# works now with updated remote script, see #28

	34  s	Test IKEv2.EN.I.1.1.6.2 Part B: Encryption Algorithm ENCR_AES_CTR
	35  M	Test IKEv2.EN.I.1.1.6.2 Part C: Encryption Algorithm ENCR_NULL
	36  S	Test IKEv2.EN.I.1.1.6.2 Part D: Integrity Algorithm AUTH_AES_XCBC_96
	37  M	Test IKEv2.EN.I.1.1.6.2 Part E: Integrity Algorithm NONE
	38  M	Test IKEv2.EN.I.1.1.6.2 Part F: Extended Sequence Numbers
	39	Test IKEv2.EN.I.1.1.6.3 Part A: Multiple Encryption Algorithms
		# works now with updated remote script, see #28

	40	Test IKEv2.EN.I.1.1.6.3 Part B: Multiple Pseudo-random Functions
	41	Test IKEv2.EN.I.1.1.6.3 Part C: Multiple Integrity Algorithms
	42	Test IKEv2.EN.I.1.1.6.3 Part D: Multiple D-H Groups
	43	Test IKEv2.EN.I.1.1.6.4 Part A
		#newly broken, see #28

	44	Test IKEv2.EN.I.1.1.6.5 Part A: Multiple Encryption Algorithms
		# works now with updated remote script, see #28

	45	Test IKEv2.EN.I.1.1.6.5 Part B: Multiple Integrity Algorithms
		# fails for similar reason to #30, SHA1 gets added twice to the proposal

	46	Test IKEv2.EN.I.1.1.6.5 Part C: Multiple Extended Sequence Numbers
	47	Test IKEv2.EN.I.1.1.6.6: Sending Multiple Proposals
	48	Test IKEv2.EN.I.1.1.6.7: Receipt of INVALID_KE_PAYLOAD
	49 *	Test IKEv2.EN.I.1.1.6.8: Receipt of NO_PROPOSAL_CHOSEN
	50  M	Test IKEv2.EN.I.1.1.6.9: Response with inconsistent SA Proposal for IKE_SA
		# works now with updated remote script, see #28

	52	Test IKEv2.EN.I.1.1.6.11 Part A: Receiving IKE_SA_INIT response with INVALID_KE_PAYLOAD
		# works now with updated remote script, see #28

	53	Test IKEv2.EN.I.1.1.6.11 Part B: Receiving IKE_SA_INIT response with INVALID_KE_PAYLOAD
		# works now with updated remote script, see #28

	54	Test IKEv2.EN.I.1.1.6.12: Creating an IKE_SA without a CHILD_SA
	55  M	Test IKEv2.EN.I.1.1.7.1: Narrowing the range of members of the set of traffic selectors
	56 *	Test IKEv2.EN.I.1.1.8.1 Part A: INVALID_IKE_SPI Different IKE_SA Initiator's SPI
	57 *	Test IKEv2.EN.I.1.1.8.1 Part B: INVALID_IKE_SPI Different IKE_SA Responder's SPI
	58 *	Test IKEv2.EN.I.1.1.8.2: INVALID_SELECTORS
	59  M	Test IKEv2.EN.I.1.1.10.1: Sending Certificate Payload
	60  M	Test IKEv2.EN.I.1.1.10.2: Sending Certificate Request Payload
	61  M	Test IKEv2.EN.I.1.1.10.3: RSA Digital Signature
	64  M	Test IKEv2.EN.I.1.1.11.2: Non zero RESERVED fields in IKE_AUTH response
	66  M	Test IKEv2.EN.I.1.1.11.4: Unrecognized Notify Message Type of Error
	68  	Test IKEv2.EN.I.1.2.1.1: Sending CREATE_CHILD_SA request
	69	Test IKEv2.EN.I.1.2.2.1: Retransmission of CREATE_CHILD_SA request
	70	Test IKEv2.EN.I.1.2.2.2: Stop of retransmission of CREATE_CHILD_SA request
	71	Test IKEv2.EN.I.1.2.3.1: Close the replaced CHILD_SA
	72	Test IKEv2.EN.I.1.2.3.2: Receipt of cryptographically valid message on the new SA
	73	Test IKEv2.EN.I.1.2.3.3: Lifetime of CHILD_SA expires
		#works now with an updated remote script that handles non-default lifetimes

	74	Test IKEv2.EN.I.1.2.3.4 Part A: Sending Multiple Transform for Rekeying CHILD_SA
	75	Test IKEv2.EN.I.1.2.3.4 Part B: Sending Multiple Transform for Rekeying CHILD_SA
	76	Test IKEv2.EN.I.1.2.3.4 Part C: Sending Multiple Transform for Rekeying CHILD_SA
	77	Test IKEv2.EN.I.1.2.3.5: Sending Multiple Proposal for Rekeying CHILD_SA
	78	Test IKEv2.EN.I.1.2.3.6: Rekeying Failure
	79	Test IKEv2.EN.I.1.2.3.7: Perfect Forward Secrecy
	80	Test IKEv2.EN.I.1.2.3.8: Use of the old CHILD_SA
	81	Test IKEv2.EN.I.1.2.4.1: Close the replaced IKE_SA
	82	Test IKEv2.EN.I.1.2.4.2: Receipt of cryptographically valid message on the new IKE_SA
	83	Test IKEv2.EN.I.1.2.4.3: Lifetime of IKE_SA expires
		#works now with an updated remote script that handles non-default lifetimes

	84	Test IKEv2.EN.I.1.2.4.4 Part A: Sending Multiple Transform for Rekeying IKE_SA
	85	Test IKEv2.EN.I.1.2.4.4 Part B: Sending Multiple Transform for Rekeying IKE_SA
	86	Test IKEv2.EN.I.1.2.4.4 Part C: Sending Multiple Transform for Rekeying IKE_SA
	87	Test IKEv2.EN.I.1.2.4.4 Part D: Sending Multiple Transform for Rekeying IKE_SA
	88	Test IKEv2.EN.I.1.2.4.5: Sending Multiple Proposal for Rekeying IKE_SA
	89	Test IKEv2.EN.I.1.2.4.6: Use of the old IKE_SA
	90	Test IKEv2.EN.I.1.2.4.7: Changing PRFs when rekeying IKE_SA
	91	Test IKEv2.EN.I.1.2.5.1: Sending CREATE_CHILD_SA request
	92	Test IKEv2.EN.I.1.2.5.2: Receipt of cryptographically valid message on the new SA
	93 *	Test IKEv2.EN.I.1.2.6.1: Simulataneous CHILD_SA Close
	94 *	Test IKEv2.EN.I.1.2.6.2: Simulataneous IKE_SA Close
	95	Test IKEv2.EN.I.1.2.6.3: Simulataneous CHILD_SA Rekeying
	96	Test IKEv2.EN.I.1.2.6.4: Simulataneous CHILD_SA Rekeying with retransmission
	97	Test IKEv2.EN.I.1.2.6.5: Simulataneous IKE_SA Rekeying
	98 	Test IKEv2.EN.I.1.2.6.6: Simulataneous IKE_SA Rekeying with retransmission
	99 *	Test IKEv2.EN.I.1.2.6.7: Closing and Rekeying CHILD_SA
	100 *	Test IKEv2.EN.I.1.2.6.8: Closing a new CHILD_SA
	101 *	Test IKEv2.EN.I.1.2.6.9: Rekeying a new CHILD_SA
	102 *	Test IKEv2.EN.I.1.2.6.10: Rekeying an IKE_SA with half-open CHILD_SAs
	103 *	Test IKEv2.EN.I.1.2.6.11: Rekeying a CHILD_SA while rekeying an IKE_SA
	104 *	Test IKEv2.EN.I.1.2.6.12: Rekeying an IKE_SA with half-closed CHILD_SAs
	105 *	Test IKEv2.EN.I.1.2.6.13: Closing a CHILD_SA while rekeying an IKE_SA
	106 * 	Test IKEv2.EN.I.1.2.6.14: Closing an IKE_SA while rekeying an IKE_SA
	107 *	Test IKEv2.EN.I.1.2.6.15: Rekeying an IKE_SA while closing the IKE_SA
	108	Test IKEv2.EN.I.1.2.7.1: Non zero RESERVED fields in CREATE_CHILD_SA response
	109 * 	Test IKEv2.EN.I.1.3.1.1: Sending INFORMATIONAL request
	110 *	Test IKEv2.EN.I.1.3.2.1: Retransmission of INFORMATIONAL request
	111 *	Test IKEv2.EN.I.1.3.2.2: Stop of retransmission of INFORMATIONAL request
	112 *	Test IKEv2.EN.I.1.3.3.1: Non zero RESERVED fields in INFORMATIONAL response
	113 *	Test IKEv2.EN.I.1.3.4.1: INVALID_SPI
	116  M 	Test IKEv2.EN.I.2.1.1.1: Sending IKE_AUTH request
	117  M	Test IKEv2.EN.I.2.1.1.2: Use of CHILD_SA
	118	Test IKEv2.EN.I.2.1.2.1: Sending CFG_REQUEST
	119	Test IKEv2.EN.I.2.1.2.2: Receipt of CFG_REPLY
	120	Test IKEv2.EN.I.2.1.2.3: Non zero RESERVED fileds in Configuration Payload
	121	Test IKEv2.EN.I.2.1.2.4: Receiving IKE_AUTH response without CFG_REPLY
	122	Test IKEv2.EN.I.2.1.2.5: Receiving unrecognized Configuration Attributes
	132 *	Test IKEv2.EN.R.1.1.3.3: Close Connections when receiving INITIAL_CONTACT
	136  M	Test IKEv2.EN.R.1.1.4.1: Receipt of a larger minor version number
	142	Test IKEv2.EN.R.1.1.4.4 Part A: Invalid payload type 1
	143	Test IKEv2.EN.R.1.1.4.4 Part B: Invalid payload type 32
	144	Test IKEv2.EN.R.1.1.4.4 Part C: Invalid payload type 49
	145	Test IKEv2.EN.R.1.1.4.4 Part D: Invalid payload type 255
	146  M	Test IKEv2.EN.R.1.1.4.5: Invalid Payload Order
	147 *	Test IKEv2.EN.R.1.1.5.1: Cookies
	148 *	Test IKEv2.EN.R.1.1.5.2: Invalid Cookies
	149 *	Test IKEv2.EN.R.1.1.5.3: Interaction of COOKIE and INVALID_KE_PAYLOAD
	150 *	Test IKEv2.EN.R.1.1.5.4: Interaction of COOKIE and INVALID_KE_PAYLOAD with unoptimized Initiator
	152 *M	Test IKEv2.EN.R.1.1.6.1 Part B: Encryption Algorithm ENCR_AES_CTR

	153	Test IKEv2.EN.R.1.1.6.1 Part C:
		# newly broken, unable to distinguish between PRF and integrity algorithms, see #28 

	154	Test IKEv2.EN.R.1.1.6.1 Part D:
		# newly broken, unable to distinguish between PRF and integrity algorithms, see #28 

	157  M	Test IKEv2.EN.R.1.1.6.2 Part B: Encryption Algorithm ENCR_AES_CTR

	158  M	Test IKEv2.EN.R.1.1.6.2 Part C: Encryption Algorithm ENCR_NULL
	159  M	Test IKEv2.EN.R.1.1.6.2 Part D: Integrity Algorithm AUTH_AES_XCBC_96
	160  M	Test IKEv2.EN.R.1.1.6.2 Part E: Integrity Algorithm NONE
	161  M	Test IKEv2.EN.R.1.1.6.2 Part F: Extended Sequence Number
	176  	Test IKEv2.EN.R.1.1.6.7: Sending of INVALID_KE_PAYLOAD
	178	Test IKEv2.EN.R.1.1.6.9: Creating an IKE_SA without a CHILD_SA
	179  M	Test IKEv2.EN.R.1.1.7.1: Narrowing the range of members of the set of traffic selectors
	181  M	Test IKEv2.EN.R.1.1.7.3: Narrowing multiple traffic selector
	182	Test IKEv2.EN.R.1.1.8.1 Part A: Different IKE_SA Initiator's SPI
	183 *	Test IKEv2.EN.R.1.1.8.1 Part B: Different IKE_SA Responder's SPI
	184 *	Test IKEv2.EN.R.1.1.8.2: INVALID_SYNTAX
	185 *	Test IKEv2.EN.R.1.1.8.3: INVALID_SELECTORS
	186  M	Test IKEv2.EN.R.1.1.10.1: Sending Certificate Payload
	187  M	Test IKEv2.EN.R.1.1.10.2: Sending Certificate Request Payload
	188  M	Test IKEv2.EN.R.1.1.10.3: RSA Digital Signature
	191  M	Test IKEv2.EN.R.1.1.11.2: Non zero RESERVED fields in IKE_AUTH response
	198  	Test IKEv2.EN.R.1.2.3.1: Receiving Delete Payload for Multiple CHILD_SA
	201	Test IKEv2.EN.R.1.2.5.2: Receipt of cryptographically protected message on the old SA and the new SA
	209	Test IKEv2.EN.R.1.2.5.6: Use of the old CHILD_SA
	212	Test IKEv2.EN.R.1.2.6.3: Use of the old IKE_SA
	213	Test IKEv2.EN.R.1.2.6.4: Close the replaced IKE_SA
	223	Test IKEv2.EN.R.1.2.6.8: D-H Transform NONE when rekeying the iKE_SA
	224	Test IKEv2.EN.R.1.2.7.1: Receipt of cryptographically valid message on the new CHILD_SA
	233  M	Test IKEv2.EN.R.2.1.1.1: Receipt of IKE_AUTH request
	234  M	Test IKEv2.EN.R.2.1.1.2: Use of CHILD_SA


> Another weirdness:
> The test spec says to set the IKE_SA Lifetime to different values
> (e.g. IKEv2.EN.I.1.1.3.7 and IKEv2.EN.I.1.1.3.6). But it is set
> to a fixed value in the default ikev2.rmt that comes with
> koi-2.1.8. The test scripts don't set the values requested by the
> test spec.

Sorry, this was not true. The test scripts do set these values and
my updated ikev2.rmt takes these into account.

> I just wonder:
> 
> - Has anyone run the IKEv2_Self_Test with more success? Any tips&tricks,
>   custom remote files, configs, whatever?

no-one, really? Any customized remote scripts that solve any of
the issues above would be really appreciated.

> 
> - Is anyone else interested in The USGv6 certification with strongSwan?
>   Has anyone talked about this with any of the accredited testing labs?

clearly, some of the problems are just in the remote scripts,
some are in strongSwan and need to be fixed to pass this test
(the PRF/integrity algorithm specification), but others remain
that are problems of the test itself. Or at least of the 1.0.3
version of it.


Thanks, more updates next week...

-- 
Jiri Bohac <jbohac at suse.cz>
SUSE Labs, SUSE CZ

-------------- next part --------------
#!/usr/bin/perl
#
# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
# NTT Advanced Technology, Yokogawa Electric Corporation.
# All rights reserved.
# 
# Redistribution and use of this software in source and binary
# forms, with or without modification, are permitted provided that
# the following conditions and disclaimer are agreed and accepted
# by the user:
# 
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with
#    the distribution.
# 
# 3. Neither the names of the copyrighters, the name of the project
#    which is related to this software (hereinafter referred to as
#    "project") nor the names of the contributors may be used to
#    endorse or promote products derived from this software without
#    specific prior written permission.
# 
# 4. No merchantable use may be permitted without prior written
#    notification to the copyrighters.
# 
# 5. The copyrighters, the project and the contributors may prohibit
#    the use of this software at any time.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTERS, THE PROJECT AND
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING
# BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.  IN NO EVENT SHALL THE
# COPYRIGHTERS, THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# $TAHI: koi/bin/remotes/manual/reboot.rmt,v 1.2 2006/06/26 01:12:30 akisada Exp $
#
# $Id: ikev2.rmt,v 1.4 2008/07/15 12:34:18 velo Exp $
#
################################################################

BEGIN {
	push(@INC, '/usr/local/koi/libdata');
	push(@INC, '..');
}

use kRemote;
use File::Basename;

my $_ps = '/bin/ps';
my $_grep = '/bin/grep';
my $_setkey = '/usr/sbin/setkey';

my $true = 1;
my $false = 0;

my $ipsec = '/usr/sbin/ipsec';
my $remote_strongswan_conf_path = '/etc/ipsec.conf';
my $pre_shared_key_base_path = '/etc/ipsec.secrets';
my @strongswan_conf = ();
my $timeout = 8;

my $basename = basename($0, '.rmt');
my $prompt = "$basename> ";

my $fd = select (STDIN);  $| = 1; select($fd);
   $fd = select (STDOUT); $| = 1; select($fd);
   $fd = select (STDERR); $| = 1; select($fd);

unless(defined(kRemoteOpen())) {
	print STDERR "fail to open session.\n";
	exit($kRemote::exitFail);
}

unless(defined(kRemoteLogin($timeout))) {
	print STDERR "fail to login.\n";
	exit($kRemote::exitFail);
}

unless(defined(kRemoteSubstituteRootWait())) {
	print STDERR "fail to substitute to Root.\n";
	exit($kRemote::exitFail);
}

my $operation = $kRemote::kRemoteOpt{'operation'};
unless(ikev2($operation)) {
	exit($kRemote::exitFail);
}

unless(defined(kRemoteLogoutWait($timeout))) {
	print STDERR "fail to logout.\n";
	exit($kRemote::exitFail);
}

unless(defined(kRemoteLogoutNoWait($timeout))) {
	print STDERR "fail to logout.\n";
	exit($kRemote::exitFail);
}

kRemoteClose();

exit($kRemote::exitPass);

########################################################################
sub rename_algo
{
	my ($algo) = @_;
	$algo =~ s/aes_xcbc/aesxcbc/;
	$algo =~ s/_cbc//;
	$algo =~ s/hmac_//;
	$algo =~ s/null_enc/null/;
	$algo =~ s/aes_ctr,(.*)/aes\1ctr/;
	return $algo;

}

sub
ikev2($)
{
	my ($operation) = @_;

	unless(defined($operation)) {
		unless(generate_strongswan_conf(\@strongswan_conf)) {
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteWriteFile($remote_strongswan_conf_path, $timeout, @strongswan_conf))) {
			print STDERR "fail to write configuration.\n";
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("chown root:wheel $remote_strongswan_conf_path", $timeout))) {
			print("fail to change file owner and group of $remote_strongswan_conf_path.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("chmod 0600 $remote_strongswan_conf_path", $timeout))) {
			print("fail to change file mode of $remote_strongswan_conf_path.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("ls -l $remote_strongswan_conf_path", $timeout))) {
			print("fail to list of $remote_strongswan_conf_path.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("$_ps -ax | $_grep -e starter -e charon", $timeout))) {
			print("fail to get process status.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("$ipsec start", $timeout))) {
			print("fail to execute spmd.\n");
			exit($kRemote::exitFail);
		}

		sleep(3);

		unless(defined(kRemoteCommandWait("$_ps -ax | $_grep -e starter -e charon", $timeout))) {
			print("fail to get process status.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("$_setkey -D", $timeout))) {
			print("fail to get SAD entries.\n");
			exit($kRemote::exitFail);
		}

		return($true);
	}

	if($operation eq 'stop') {
		unless(defined(kRemoteCommandWait("$_setkey -D", $timeout))) {
			print("fail to get SAD entries.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("$_setkey -DP", $timeout))) {
			print("fail to get SPD entries.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("$_ps -ax | $_grep -e starter -e charon", $timeout))) {
			print("fail to get process status.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("$ipsec stop", $timeout))) {
			print("fail to kill processes by name.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("$_ps -ax | $_grep -e starter -e charon", $timeout))) {
			print("fail to get process status.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("$_setkey -F", $timeout))) {
			print("fail to flush SAD entries.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("$_setkey -FP", $timeout))) {
			print("fail to flush SPD entries.\n");
			exit($kRemote::exitFail);
		}

		sleep(3);

		unless(defined(kRemoteCommandWait("$_setkey -D", $timeout))) {
			print("fail to get SAD entries.\n");
			exit($kRemote::exitFail);
		}

		unless(defined(kRemoteCommandWait("$_setkey -DP", $timeout))) {
			print("fail to get SPD entries.\n");
			exit($kRemote::exitFail);
		}

		return($true);
	}

	if($operation eq 'initiate') {
		my $host = $kRemote::kRemoteOpt{'target'};
		unless(defined(kRemoteCommandWait("ping6 -n -c 1 $host", $timeout))) {
			print("fail to send ICMPv6 ECHO_REQUEST packets to network hosts.\n");
			exit($kRemote::exitFail);
		}


		return($true);
	}

	print("unknown operation -- $operation\n");
	return($false);
}



sub
generate_strongswan_conf($)
{
	my ($conf) = @_;

	my $num = undef;

	# config
	push(@$conf, 'config setup');
	push(@$conf, '        crlcheckinterval=180');
	push(@$conf, '        strictcrlpolicy=no');
	push(@$conf, '        plutostart=no');
	push(@$conf, '        charondebug="ike 4, knl 4, net 4, enc 4"');

	# conn %default
	push(@$conf, 'conn %default');
	push(@$conf, '        rekeymargin=5s');
#	push(@$conf, '        keyingtries=1');
	push(@$conf, '        ikelifetime=60s');
	push(@$conf, '        keylife=30s');
	push(@$conf, '        mobike=no');
	push(@$conf, '        keyexchange=ikev2');
	push(@$conf, '        ike=3des-sha-modp1024');
	push(@$conf, '        esp=3des-sha1');
	push(@$conf, '        leftauth=psk');
	push(@$conf, '        rightauth=psk');
#	push(@$conf, '        rekey=no');

	# conn host-host
	push(@$conf, 'conn host-host');

	## left
	$num = $kRemote::kRemoteOpt{'ikev2.interface.ike.num'};
	if($num) {
		for (my $d = 0; $d < $num; $d ++) {
			my $prefix = sprintf("%s.%d", 'ikev2.interface.ike', $d);
			my $address = $kRemote::kRemoteOpt{"$prefix.address"};
			push(@$conf, "        left=$address");
		}
	}

	## right
        $num = $kRemote::kRemoteOpt{'ikev2.remote.num'};
	if($num) {
		for(my $d = 0; $d < $num; $d ++) {
			my $prefix = sprintf("%s.%d", 'ikev2.remote', $d);
			my $address = $kRemote::kRemoteOpt{"$prefix.ikev2.peers_ipaddr.address"};
			push(@$conf, "        right=$address");
		}
	}


	#lifetimes
	$kmp_sa_lifetime_time=$kRemote::kRemoteOpt{'ikev2.remote.0.ikev2.kmp_sa_lifetime_time'};
	if ($kmp_sa_lifetime_time) {
		push(@$conf, "        ikelifetime=${kmp_sa_lifetime_time}s");
	}
	$ipsec_sa_lifetime_time=$kRemote::kRemoteOpt{'ikev2.ipsec.0.ipsec_sa_lifetime_time'};
	if ($ipsec_sa_lifetime_time) {
		push(@$conf, "        keylife=${ipsec_sa_lifetime_time}s");
	}

	#IKE crypto
	my @algos = ();
        $num = $kRemote::kRemoteOpt{'ikev2.remote.0.ikev2.kmp_enc_alg.num'};
	if($num) {
		for(my $d = 0; $d < $num; $d ++) {
			my $prefix = sprintf("%s.%d", 'ikev2.remote.0.ikev2.kmp_enc_alg', $d);
			my $algo = $kRemote::kRemoteOpt{"$prefix"};
			$algo = rename_algo($algo);
			push(@algos, $algo);
		}
	}
	$num = $kRemote::kRemoteOpt{'ikev2.remote.0.ikev2.kmp_hash_alg.num'};
	if($num) {
		for(my $d = 0; $d < $num; $d ++) {
			my $prefix = sprintf("%s.%d", 'ikev2.remote.0.ikev2.kmp_hash_alg', $d);
			my $algo = $kRemote::kRemoteOpt{"$prefix"};
			$algo = rename_algo($algo);
			push(@algos, $algo);
		}
	}
	$num = $kRemote::kRemoteOpt{'ikev2.remote.0.ikev2.kmp_prf_alg.num'};
	if($num) {
		for(my $d = 0; $d < $num; $d ++) {
			my $prefix = sprintf("%s.%d", 'ikev2.remote.0.ikev2.kmp_prf_alg', $d);
			my $algo = $kRemote::kRemoteOpt{"$prefix"};
			$algo = rename_algo($algo);
			push(@algos, $algo);
		}
	}
	$num = $kRemote::kRemoteOpt{'ikev2.remote.0.ikev2.kmp_dh_group.num'};
	if($num) {
		for(my $d = 0; $d < $num; $d ++) {
			my $prefix = sprintf("%s.%d", 'ikev2.remote.0.ikev2.kmp_dh_group', $d);
			my $algo = $kRemote::kRemoteOpt{"$prefix"};
			$algo = rename_algo($algo);
			push(@algos, $algo);
		}
	}
	if (@algos) {
		push(@$conf, "        ike=" . join("-", @algos) . "!");
	}

	#ESP crypto
	my @algos = ();
        $num = $kRemote::kRemoteOpt{'ikev2.sa.0.esp_enc_alg.num'};
	if($num) {
		for(my $d = 0; $d < $num; $d ++) {
			my $prefix = sprintf("%s.%d", 'ikev2.sa.0.esp_enc_alg', $d);
			my $algo = $kRemote::kRemoteOpt{"$prefix"};
			$algo = rename_algo($algo);
			push(@algos, $algo);
		}
	}
        $num = $kRemote::kRemoteOpt{'ikev2.sa.0.esp_auth_alg.num'};
	if($num) {
		for(my $d = 0; $d < $num; $d ++) {
			my $prefix = sprintf("%s.%d", 'ikev2.sa.0.esp_auth_alg', $d);
			my $algo = $kRemote::kRemoteOpt{"$prefix"};
			$algo = rename_algo($algo);
			push(@algos, $algo);
		}
	}
	if (@algos) {
		push(@$conf, "        esp=" . join("-", @algos) . "!");
	}

	## leftid, rightid
	$num = $kRemote::kRemoteOpt{'ikev2.remote.num'};
	if($num) {
		for(my $d = 0; $d < $num; $d ++) {
			my $prefix = sprintf("%s.%d", 'ikev2.remote', $d);
			my $ipaddr = undef;
			my $sub_num = undef;

			## leftid
			if ($kRemote::kRemoteOpt{"$prefix.ikev2.my_id.ipaddr.num"}) {
				# ipaddr
				$sub_num = $kRemote::kRemoteOpt{"$prefix.ikev2.my_id.ipaddr.num"};
				if ($sub_num) {
					for (my $d = 0; $d < $sub_num; $d++) {
						$ipaddr = $kRemote::kRemoteOpt{"$prefix.ikev2.my_id.ipaddr.$d"};
						push(@$conf, "        leftid=$ipaddr");
					}
				}
			}

			if ($kRemote::kRemoteOpt{"$prefix.ikev2.my_id.fqdn.num"}) {
				# fqdn
				$sub_num = $kRemote::kRemoteOpt{"$prefix.ikev2.my_id.fqdn.num"};
				if ($sub_num) {
					for (my $d = 0; $d < $sub_num; $d++) {
						my $fqdn = $kRemote::kRemoteOpt{"$prefix.ikev2.my_id.fqdn.$d"};
						push(@$conf, "        leftid=$fqdn");
					}
				}
			}
			if ($kRemote::kRemoteOpt{"$prefix.ikev2.my_id.rfc822addr.num"}) {
				# rfc822 addr
				$sub_num = $kRemote::kRemoteOpt{"$prefix.ikev2.my_id.rfc822addr.num"};
				if ($sub_num) {
					for (my $d = 0; $d < $sub_num; $d++) {
						my $rfc822addr = $kRemote::kRemoteOpt{"$prefix.ikev2.my_id.rfc822addr.$d"};
						push(@$conf, "        leftid=$rfc822addr");
					}
				}
			}

			## rightid
			if ($kRemote::kRemoteOpt{"$prefix.ikev2.peers_id.ipaddr.num"}) {
				# ipaddr
				$sub_num = $kRemote::kRemoteOpt{"$prefix.ikev2.peers_id.ipaddr.num"};
				if ($sub_num) {
					for (my $d = 0; $d < $sub_num; $d++) {
						$ipaddr = $kRemote::kRemoteOpt{"$prefix.ikev2.peers_id.ipaddr.$d"};
						push(@$conf, "        rightid=$ipaddr");
					}
				}
			}
			if ($kRemote::kRemoteOpt{"$prefix.ikev2.peers_id.fqdn.num"}) {
				# fqdn
				$sub_num = $kRemote::kRemoteOpt{"$prefix.ikev2.peers_id.fqdn.num"};
				if ($sub_num) {
					for (my $d = 0; $d < $sub_num; $d++) {
						my $fqdn = $kRemote::kRemoteOpt{"$prefix.ikev2.peers_id.fqdn.$d"};
						push(@$conf, "        rightid=$fqdn");
					}
				}
			}
			if ($kRemote::kRemoteOpt{"$prefix.ikev2.peers_id.rfc822addr.num"}) {
				# rfc822 addr
				$sub_num = $kRemote::kRemoteOpt{"$prefix.ikev2.peers_id.rfc822addr.num"};
				if ($sub_num) {
					for (my $d = 0; $d < $sub_num; $d++) {
						my $rfc822addr = $kRemote::kRemoteOpt{"$prefix.ikev2.peers_id.rfc822addr.$d"};
						push(@$conf, "        rightid=$rfc822addr");
					}
				}
			}


			my $pre_shared_key_local = $kRemote::kRemoteOpt{"$prefix.ikev2.pre_shared_key.local"};
			my $pre_shared_key_remote = $kRemote::kRemoteOpt{"$prefix.ikev2.pre_shared_key.remote"};

			unless (generate_pre_shared_key($pre_shared_key_base_path, $pre_shared_key_local, $pre_shared_key_remote)) {
				return($false);
			}
		}
	}

	## leftfirewall
##	push(@$conf, '        leftfirewall=yes');

	## type
	$num = $kRemote::kRemoteOpt{'ikev2.policy.num'};
	if($num) {
		for(my $d = 0; $d < $num; $d ++) {
			my $sub_num = undef;

			my $prefix = sprintf("%s.%d", 'ikev2.policy', $d);
			my $ipsec_mode = $kRemote::kRemoteOpt{"$prefix.ipsec_mode"};
			if ($ipsec_mode eq 'transport') {
				push(@$conf, '        type=transport');
			}
		}
	}

	##
	push(@$conf, '        auto=route');

	#push(@$conf, '        ');

	return($true);
}



sub
generate_pre_shared_key($$$)
{
	my ($path, $local, $remote) = @_;

	if($local ne $remote) {
		print("racoon2 doesn\'t support different pre-shared keys between initiator and responder.\n");
		exit($kRemote::exitNS);
	}

	my @psk = ();
	push(@psk, ": PSK '$local'");
	# XXX: use kRemoteCopy() for handling binary pre-shared key
	unless(defined(kRemoteWriteFile($path, $timeout, @psk))) {
		print STDERR "fail to write configuration.\n";
		exit($kRemote::exitFail);
	}


#	unless(defined(kRemoteCommandWait("echo -n : PSK \\'$local\\' > $path", $timeout))) {
#		print("fail to write out pre_shared_key to $path.\n");
#		exit($kRemote::exitFail);
#	}

	unless(defined(kRemoteCommandWait("cat -n $path", $timeout))) {
		print("fail to print $path.\n");
		exit($kRemote::exitFail);
	}

	unless(defined(kRemoteCommandWait("chown root:wheel $path", $timeout))) {
		print("fail to change file owner and group of $path.\n");
		exit($kRemote::exitFail);
	}

	unless(defined(kRemoteCommandWait("chmod 0600 $path", $timeout))) {
		print("fail to change file mode of $path.\n");
		exit($kRemote::exitFail);
	}

	unless(defined(kRemoteCommandWait("ls -l $path", $timeout))) {
		print("fail to list of $path.\n");
		exit($kRemote::exitFail);
	}

	return($true);
}



sub generate_id_key_id($$)
{
	my ($path, $id) = @_;

	unless (defined(kRemoteCommandWait("touch $path", $timeout))) {
		print("fail to touch file $path\n");
		exit($kRemote::exitFail);
	}

	unless(defined(kRemoteCommandWait("perl -e 'open(OUT, \">$path\"); print(OUT pack(\"H*\", \"$id\")); close(OUT);'", $timeout))) {
		print("fail to set keyid value to $path.\n");
		exit($kRemote::exitFail);
	}

	unless(defined(kRemoteCommandWait("chown root:wheel $path", $timeout))) {
		print("fail to change file owner and group of $path.\n");
		exit($kRemote::exitFail);
	}

	unless(defined(kRemoteCommandWait("chmod 0600 $path", $timeout))) {
		print("fail to change file mode of $path.\n");
		exit($kRemote::exitFail);
	}

	unless(defined(kRemoteCommandWait("ls -l $path", $timeout))) {
		print("fail to list of $path.\n");
		exit($kRemote::exitFail);
	}

	return($true);
}



More information about the Users mailing list