[Openswan dev] SPI generation by netlink_get_spi()

Andreas Steffen andreas.steffen at strongsec.net
Thu Jul 29 16:04:53 CEST 2004


Hi Herbert,

one of my customers has a problem with Openswan/strongSwan running
on a 2.6.6 kernel connecting to freeswan-2.04 with X.509 patch 1.6.3.
I was able to re-enact the scenario in question on my 2.6.7 test platform.

The problem can occur if a connection is started by auto=start as
in the following example:

conn uwe
     keyingtries=0
     authby=rsasig
     left=%defaultroute
     leftcert=mypubkey.pem
     leftrsasigkey=%cert
     rightid="C=..."
     right=194.76.232.140
     rightsubnet=10.0.0.0/8
     auto=start

auto=start automatically installs a %trap eroute:

: | *received whack message
: | route owner of "uwe" unrouted: NULL; eroute owner: NULL
: | route owner of "uwe" unrouted: NULL; eroute owner: NULL
: | route_and_eroute with c: uwe (next: none) ero:null esr:{(nil)} ro:null
     rosr:{(nil)} and state: 0
: | add eroute 10.0.0.0/8:0 -> 145.254.54.68/32:0 => int.104 at 145.254.54.68:0
: | eroute_connection add eroute 145.254.54.68/32:0 -> 10.0.0.0/8:0 => %trap:0

next the conn uwe is initiated

: | Queuing pending Quick Mode with 194.76.232.140 "uwe"

: "uwe" #1: initiating Main Mode

starting with Main Mode, with a pending Quick Mode.

Due to a stray ICMP message occuring during the Main Mode Negotiation
the %trap eroute gets triggered and a narrow %hold eroute is installed:

: | *received kernel message
: | netlink_get: XFRM_MSG_ACQUIRE message
: | add bare shunt 0x8d854b0
      145.254.54.68/32:0 -> 10.128.9.1/32:0 => %hold:1 0    %acquire-netlink
: | initiate on demand from 145.254.54.68:0 to 10.128.9.1:0 proto=1 state:
     fos_start because: whack
: | find_connection: looking for policy for connection: 145.254.54.68:1/0 ->
      10.128.9.1:1/0

Next a search for a matching connection is started and und conn uwe is found:

: | find_connection: conn "uwe" has compatible peers:
      145.254.54.68/32->10.0.0.0/8 [pri: 16793612]
: | find_connection: comparing best "uwe" [pri:16793612]{0x8d82b68} (child none)
      to "uwe" [pri:16793612]{0x8d82b68} (child none)
: | find_connection: concluding with "uwe" [pri:16793612]{0x8d82b68}
     kind=CK_PERMANENT
: | eroute_connection replace %trap with broad %hold eroute 145.254.54.68/32:0
      -> 10.0.0.0/8:0 => %hold:0
: | delete narrow %hold eroute 145.254.54.68/32:0 -> 10.128.9.1/32:0 => %hold:1
: | delete bare shunt 0x8d854b0 145.254.54.68/32:0 -> 10.128.9.1/32:0 => %hold:1
     0    %acquire-netlink

Since a Main Mode negotiation for conn uwe is already under way, a Quick Mode
negotiation is queued in the pending queue.
Quick Mode

: | Queuing pending Quick Mode with 194.76.232.140 "uwe"

After the successful establishment of the phase 1 ISAKMP SA, the first
pending Quick Mode is started:

: "uwe" #1: ISAKMP SA established

: | unqueuing pending Quick Mode with 194.76.232.140 "uwe"
: | creating state object #2 at 0x8d86220
: "uwe" #2: initiating Quick Mode RSASIG+ENCRYPT+TUNNEL+PFS+UP {using isakmp#1}
: |    message ID:  65 7e 1a 0f
: | netlink_get_spi: allocated 0x9f4c9788 for esp.0 at 145.254.54.68
: | SPI  9f 4c 97 88

The netlink interface of the 2.6 kernel is used to request an SPI for
the IPsec SA.

Immediately after the first Quick Mode message the second pending Quick Mode
is inititated:

: | unqueuing pending Quick Mode with 194.76.232.140 "uwe"
: | creating state object #3 at 0x8d876d0
: "uwe" #3: initiating Quick Mode RSASIG+ENCRYPT+TUNNEL+PFS+UP {using isakmp#1}
: |    message ID:  a1 01 a2 b2
: | netlink_get_spi: allocated 0x9f4c9788 for esp.0 at 145.254.54.68
: | SPI  9f 4c 97 88

And here the error happens. The two Quick Mode negotiations have different
Message IDs (65 7e 1a 0f versus a1 01 a2 b2) which will cause two phase2
state objects to be created on the peer side but the generated SPI 9f 4c 97 88
is the same. This will trigger the assertion passert(0) in 
kernel_pfkey.c:finish_pfkey_msg() in freeswan-2.0x because twice the same 
SADB_ADD command is executed for the outbound esp. Removing the assertion
as in Openswan does not help - several retrials will not succeed in setting
up the IPsec SA.

Looking at kernel.c:get_spi() I see that if KLIPS is used, each call
increases the SPI by one (spi++) so that always a unique SPI is generated
and therefore the problem never occurs. But using the native IPsec stack
of the 2.6 kernel causes netlink_get_spi() to be called instead:

static ipsec_spi_t
netlink_get_spi(const ip_address *src
               , const ip_address *dst
               , int proto
               , bool tunnel_mode
               , unsigned reqid
               , ipsec_spi_t min
               , ipsec_spi_t max
               , const char *text_said)

Because all input parameters are the same (I suspect that both Quick
Modes also use the same reqid, although I couldn't document this yet)
I assume this causes netlink to return the same SPI.

How can this be fixed? Can netlink be forced to generate unique
SPIs by some other means or must the reqids be different?

Regards

Andreas

=======================================================================
Andreas Steffen                   e-mail: andreas.steffen at strongsec.com
strongSec GmbH                    home:   http://www.strongsec.com
Alter Zürichweg 20                phone:  +41 1 730 80 64
CH-8952 Schlieren (Switzerland)   fax:    +41 1 730 80 65
==========================================[strong internet security]===


More information about the Dev mailing list