Project

General

Profile

Issue #989

libsoup fetcher comflicts with make_before_break feature

Added by Tao Su about 7 years ago. Updated over 6 years ago.

Status:
Closed
Priority:
Normal
Category:
charon
Affected version:
5.3.2
Resolution:
No change required

Description

Hi, I am working on a customised plugin for charon which needs to use libsoup to communicate with a http webserver. When I activate the make_before_break feature introduced after version 5.3.0, the first http request can succeed, but the second time will fail and the network connection of the client machine will be fully dropped (the IPsec connection and the regular Internet connection will both be dropped), and Internet connection will resume after several minutes.

I checked in the code function after function, and found that in the second http request, everything stops at this point:

    DBG2(DBG_LIB, "sending http request to '%s'...", uri);
    soup_session_send_message(data.session, message);

in the soup_fetcher.c.

The format of the data.session and the message should be correct otherwise the first post request to the http webserver will not work.

Here is the output log when the second http request fails:

15[IKE] deleting IKE_SA test-ned[1] between 192.168.1.38[own]...192.168.1.110[C=CH, O=strongSwan, CN=ned6]
07[LIB] HTTP request failed: Cannot connect to destination (verifier)

But when I turn of the make_before_break option in the charon.conf, the http request with libsoup works fine, but the IPsec tunnel will have a gap during the re-authentication.

Please let me know how you think about this issue, any help is welcome.

newRA.patch (17.2 KB) newRA.patch the oat-attest patch Tao Su, 16.06.2015 09:20
ip_log_after_ping (6.42 KB) ip_log_after_ping after the server ping to the client machine Tao Su, 23.06.2015 19:26
ip_log_after_pass (8.92 KB) ip_log_after_pass after the pass conn is created in ipsec.conf Tao Su, 23.06.2015 19:26
ip_log_init (2.55 KB) ip_log_init the initial connection without pass conn, and before the server ping to the client Tao Su, 23.06.2015 19:26

History

#1 Updated by Tobias Brunner about 7 years ago

  • Status changed from New to Feedback
  • Priority changed from High to Normal

network connection of the client machine will be fully dropped (the IPsec connection and the regular Internet connection will both be dropped)

That sounds strange. How does the failed tunnel have an influence on the regular network connectivity?

What exactly does your plugin do? When do these requests occur?

Anyway, the problem with the fetcher makes sense if it isn't possible in your setup to reach the HTTP server via the IPsec tunnel. That wouldn't be directly related to libsoup, but would happen with any fetcher. To make sure you can reach that server you might consider adding a passthrough policy (type=passthrough) that allows traffic to it outside the IPsec tunnel.

#2 Updated by Tao Su about 7 years ago

network connection of the client machine will be fully dropped (the IPsec connection and the regular Internet connection will both be dropped)

That sounds strange. How does the failed tunnel have an influence on the regular network connectivity?

I agree with you, this issue is quite strange, I don't know why it happens.
What exactly does your plugin do? When do these requests occur?

The plugin is quite simple, it is used to call the fetcher provided by the libstrongswan to send a http request to the OpenAttestation Appraiser, and asks it to attest the node which it is connecting to, if the received result shows the other node is not in the right status or does not fulfil the criteria, drop the ipsec connection.

This requests occur when the two peers authenticating each other, and this plugin is for charon daemon.

Anyway, the problem with the fetcher makes sense if it isn't possible in your setup to reach the HTTP server via the IPsec tunnel. That wouldn't be directly related to libsoup, but would happen with any fetcher. To make sure you can reach that server you might consider adding a passthrough policy (type=passthrough) that allows traffic to it outside the IPsec tunnel.

In my setup, I have change the policy in the IPsec server side, that all the traffic from the client will go through the server, and the server will masquerade the traffic. When the IPsec tunnel is stable (i.e. no re-authentication of each other), the client can reach the http server, but once the peers start to re-authencate, the connection is dropped.

I will try to add a passthrough policy and see if this works, but I would like to be persistent, what if I want all the traffic to go through the IPsec tunnel, do you think there is a way to allow this option?

Thank you very much!

#3 Updated by Tobias Brunner about 7 years ago

The plugin is quite simple, it is used to call the fetcher provided by the libstrongswan to send a http request to the OpenAttestation Appraiser, and asks it to attest the node which it is connecting to, if the received result shows the other node is not in the right status or does not fulfil the criteria, drop the ipsec connection.

Did you see that strongSwan already implements a whole bunch of TCG protocols for this purpose?

When the IPsec tunnel is stable (i.e. no re-authentication of each other), the client can reach the http server, but once the peers start to re-authencate, the connection is dropped.

But if you use make-before-break reauthentication the existing tunnel should be valid until the new tunnel is established so you should always be able to reach the HTTP server if it is reachable via IPsec tunnel (that's the advantage of this method, you always have a tunnel).

#4 Updated by Tao Su about 7 years ago

Did you see that strongSwan already implements a whole bunch of TCG protocols for this purpose?

Yes, we do know stongswan has provided something similar, but we have implemented some more features with OpenAttestation. Since it only requires to send a http request, we decided not to change to strongswan's TCG related functions, but to develop a simple plugin for achieve this function.
But if you use make-before-break reauthentication the existing tunnel should be valid until the new tunnel is established so you should always be able to reach the HTTP server if it is reachable via IPsec tunnel (that's the advantage of this method, you always have a tunnel).

Yes, I know this is supposed to work as you said, that is why we changed the version from 5.2.0 to 5.3.2. But the problem exists, and that is why I opened this issue here. Since this http request will need several seconds to get the result, may it be a time out error?

As I tested, the connection is dropped before the IKE_SA is deleted, but in the beginning of sending the HTTP request.

#5 Updated by Tobias Brunner about 7 years ago

Since this http request will need several seconds to get the result, may it be a time out error?

When exactly do you trigger the HTTP request? In what hook on listener_t? Could you provide the source code or your plugin?

As I tested, the connection is dropped before the IKE_SA is deleted, but in the beginning of sending the HTTP request.

What do you mean? Could you provide some logs?

#6 Updated by Tao Su about 7 years ago

yes, the http request is hooked to the listener. I upload the plugin patch which you can directly use it in strongswan 5.3.2.

Here is the log that from the beginning of charon daemon to the end of connection dropping.

Starting strongSwan 5.3.2 IPsec [starter]...
00[DMN] Starting IKE charon daemon (strongSwan 5.3.2, Linux 3.13.0-54-generic, x86_64)
00[CFG] loading ca certificates from '/etc/strongswan/ipsec.d/cacerts'
00[CFG]   loaded ca certificate "C=CH, O=strongSwan, CN=strongSwan CA" from '/etc/strongswan/ipsec.d/cacerts/caCert-test-ned.der'
00[CFG]   loaded ca certificate "C=CH, O=strongSwan, CN=strongSwan CA" from '/etc/strongswan/ipsec.d/cacerts/caCert.der'
00[CFG] loading aa certificates from '/etc/strongswan/ipsec.d/aacerts'
00[CFG] loading ocsp signer certificates from '/etc/strongswan/ipsec.d/ocspcerts'
00[CFG] loading attribute certificates from '/etc/strongswan/ipsec.d/acerts'
00[CFG] loading crls from '/etc/strongswan/ipsec.d/crls'
00[CFG] loading secrets from '/etc/strongswan/ipsec.secrets'
00[CFG]   loaded IKE secret for %any
00[LIB] loaded plugins: charon aes des rc2 sha1 sha2 md5 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem fips-prf gmp xcbc cmac hmac soup attr kernel-netlink resolve socket-default stroke updown xauth-generic oat_attest
00[JOB] spawning 16 worker threads
charon (11251) started after 20 ms
05[CFG] received stroke: add connection 'test-ned'
05[CFG] left nor right host is our side, assuming left=local
05[CFG] added configuration 'test-ned'
08[CFG] received stroke: initiate 'test-ned'
08[IKE] initiating IKE_SA test-ned[1] to 192.168.1.110
08[ENC] generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(HASH_ALG) ]
08[NET] sending packet: from 192.168.1.76[500] to 192.168.1.110[500] (724 bytes)
09[NET] received packet: from 192.168.1.110[500] to 192.168.1.76[500] (456 bytes)
09[ENC] parsed IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(HASH_ALG) N(MULT_AUTH) ]
09[IKE] sending cert request for "C=CH, O=strongSwan, CN=strongSwan CA" 
09[IKE] sending cert request for "C=CH, O=strongSwan, CN=strongSwan CA" 
09[IKE] authentication of 'own' (myself) with pre-shared key
09[IKE] establishing CHILD_SA test-ned
09[ENC] generating IKE_AUTH request 1 [ IDi N(INIT_CONTACT) CERTREQ IDr AUTH CPRQ(ADDR DNS) SA TSi TSr N(MOBIKE_SUP) N(ADD_4_ADDR) N(ADD_4_ADDR) N(MULT_AUTH) N(EAP_ONLY) ]
09[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (508 bytes)
10[NET] received packet: from 192.168.1.110[4500] to 192.168.1.76[4500] (1340 bytes)
10[ENC] parsed IKE_AUTH response 1 [ IDr CERT AUTH CPRP(ADDR) SA TSi TSr N(AUTH_LFT) N(MOBIKE_SUP) N(NO_ADD_ADDR) ]
10[IKE] received end entity cert "C=CH, O=strongSwan, CN=ned6" 
10[CFG]   using certificate "C=CH, O=strongSwan, CN=ned6" 
10[CFG]   using trusted ca certificate "C=CH, O=strongSwan, CN=strongSwan CA" 
10[CFG] checking certificate status of "C=CH, O=strongSwan, CN=ned6" 
10[CFG] certificate status is not available
10[CFG]   reached self-signed root ca with a path length of 0
10[IKE] authentication of 'C=CH, O=strongSwan, CN=ned6' with RSA_EMSA_PKCS1_SHA256 successful
10[LIB] 
10[LIB] 
10[LIB] ---------- Remote Attestation begins ----------
10[LIB] 
10[LIB] Extracted Common Name from peer certificate: ned6
10[LIB] SHA1 of the peer certificate: 295933e408f257333a458fbd6acf24b0443c016a
10[LIB] 
10[LIB] User terminal -> verifier:
10[LIB] request: { "hosts": [ "ned6" ], "analysisType": "load-time+check-cert,l_req=l1|>=,cert_digest=295933e408f257333a458fbd6acf24b0443c016a" }
10[LIB] 
10[LIB] Verifier -> user terminal:
10[LIB] response: {"hosts":[{"analysis_details":{"name":"load-time+check-cert","output":"","result":"true","status":"ANALYSIS_COMPLETED"},"host_name":"ned6","report_is_valid":"true","trust_lvl":"trusted","url":"http://verifier/OAT/report.php?id=501","vtime":"2015-06-16T09:33:06+02:00"}]}
10[LIB] 
10[LIB] Host: ned6, status: trusted
10[LIB] 
10[LIB] ---------- Remote Attestation ends ----------
10[LIB] 
10[LIB] 
10[IKE] IKE_SA test-ned[1] established between 192.168.1.76[own]...192.168.1.110[C=CH, O=strongSwan, CN=ned6]
10[IKE] scheduling reauthentication in 16s
10[IKE] maximum IKE_SA lifetime 26s
10[IKE] installing new virtual IP 10.1.0.1
10[IKE] CHILD_SA test-ned{1} established with SPIs c9f915d1_i c3bf1f6c_o and TS 10.1.0.1/32 === 0.0.0.0/0 
10[IKE] received AUTH_LIFETIME of 10240s, reauthentication already scheduled in 16s
10[IKE] peer supports MOBIKE
05[IKE] reauthenticating IKE_SA test-ned[1]
05[IKE] installing new virtual IP 10.1.0.1
05[IKE] initiating IKE_SA test-ned[2] to 192.168.1.110
05[ENC] generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(HASH_ALG) ]
05[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (724 bytes)
07[NET] received packet: from 192.168.1.110[4500] to 192.168.1.76[4500] (456 bytes)
07[ENC] parsed IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(HASH_ALG) N(MULT_AUTH) ]
07[IKE] sending cert request for "C=CH, O=strongSwan, CN=strongSwan CA" 
07[IKE] sending cert request for "C=CH, O=strongSwan, CN=strongSwan CA" 
07[IKE] authentication of 'own' (myself) with pre-shared key
07[IKE] establishing CHILD_SA test-ned
07[ENC] generating IKE_AUTH request 1 [ IDi CERTREQ IDr AUTH CPRQ(ADDR DNS) SA TSi TSr N(MOBIKE_SUP) N(ADD_4_ADDR) N(ADD_4_ADDR) N(MULT_AUTH) N(EAP_ONLY) ]
07[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (508 bytes)
08[NET] received packet: from 192.168.1.110[4500] to 192.168.1.76[4500] (1340 bytes)
08[ENC] parsed IKE_AUTH response 1 [ IDr CERT AUTH CPRP(ADDR) SA TSi TSr N(AUTH_LFT) N(MOBIKE_SUP) N(NO_ADD_ADDR) ]
08[IKE] received end entity cert "C=CH, O=strongSwan, CN=ned6" 
08[CFG]   using certificate "C=CH, O=strongSwan, CN=ned6" 
08[CFG]   using trusted ca certificate "C=CH, O=strongSwan, CN=strongSwan CA" 
08[CFG] checking certificate status of "C=CH, O=strongSwan, CN=ned6" 
08[CFG] certificate status is not available
08[CFG]   reached self-signed root ca with a path length of 0
08[IKE] authentication of 'C=CH, O=strongSwan, CN=ned6' with RSA_EMSA_PKCS1_SHA256 successful
08[LIB] 
08[LIB] 
08[LIB] ---------- Remote Attestation begins ----------
08[LIB] 
08[LIB] Extracted Common Name from peer certificate: ned6oD
08[LIB] SHA1 of the peer certificate: 295933e408f257333a458fbd6acf24b0443c016a
08[LIB] 
08[LIB] User terminal -> verifier:
08[LIB] request: { "hosts": [ "ned6" ], "analysisType": "load-time+check-cert,l_req=l1|>=,cert_digest=295933e408f257333a458fbd6acf24b0443c016a" }

### this is where the connection stops working 

14[IKE] deleting IKE_SA test-ned[1] between 192.168.1.76[own]...192.168.1.110[C=CH, O=strongSwan, CN=ned6]
08[LIB] HTTP request failed: Cannot connect to destination (verifier)
08[LIB] 
08[LIB] Verifier -> user terminal:
08[LIB] response: 
08[LIB] 
08[LIB] WARNING! WARNING! WARNING! Host: ned6, status: unknown
08[LIB] 
08[LIB] ---------- Remote Attestation ends ----------
08[LIB] 
08[LIB] 
08[IKE] final authorization hook forbids IKE_SA, cancelling
08[ENC] generating INFORMATIONAL request 2 [ N(AUTH_FAILED) ]
08[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (76 bytes)
14[IKE] sending DELETE for IKE_SA test-ned[1]
14[ENC] generating INFORMATIONAL request 2 [ D ]
14[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (76 bytes)
15[NET] received packet: from 192.168.1.110[4500] to 192.168.1.76[4500] (76 bytes)
15[ENC] parsed INFORMATIONAL request 0 [ D ]
15[IKE] received DELETE for IKE_SA test-ned[1]
15[IKE] deleting IKE_SA test-ned[1] between 192.168.1.76[own]...192.168.1.110[C=CH, O=strongSwan, CN=ned6]
15[IKE] IKE_SA deleted
15[ENC] generating INFORMATIONAL response 0 [ ]
15[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (76 bytes)
10[NET] received packet: from 192.168.1.110[4500] to 192.168.1.76[4500] (76 bytes)
10[ENC] parsed INFORMATIONAL request 0 [ D ]
10[IKE] received retransmit of request with ID 0, retransmitting response
10[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (76 bytes)
11[NET] received packet: from 192.168.1.110[4500] to 192.168.1.76[4500] (76 bytes)
11[ENC] parsed INFORMATIONAL request 0 [ D ]
11[IKE] received retransmit of request with ID 0, retransmitting response
11[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (76 bytes)
12[NET] received packet: from 192.168.1.110[4500] to 192.168.1.76[4500] (76 bytes)
12[ENC] parsed INFORMATIONAL request 0 [ D ]
12[IKE] received retransmit of request with ID 0, retransmitting response
12[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (76 bytes)
04[NET] received packet: from 192.168.1.110[4500] to 192.168.1.76[4500] (76 bytes)
04[ENC] parsed INFORMATIONAL request 0 [ D ]
04[IKE] received retransmit of request with ID 0, retransmitting response
04[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (76 bytes)
06[NET] received packet: from 192.168.1.110[4500] to 192.168.1.76[4500] (76 bytes)
06[ENC] parsed INFORMATIONAL request 0 [ D ]
06[IKE] received retransmit of request with ID 0, retransmitting response
06[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (76 bytes)
07[NET] received packet: from 192.168.1.110[4500] to 192.168.1.76[4500] (76 bytes)
07[ENC] parsed INFORMATIONAL response 2 [ ]
07[IKE] IKE_SA deleted

I only changed the ip addresses from the public ones to the private ones, the rest is what I got from the terminal.

#7 Updated by Tobias Brunner about 7 years ago

The problem is that at the point where the HTTP request occurs the responder already has the IPsec SAs and policies installed, but the client has not.

Let me illustrate what I mean. In the initial exchange the following happens:

IKE_SA_INIT request -->
                              <-- IKE_SA_INIT response
IKE_AUTH request -->
                                  authentication successful
                                  install SAs and policies (1)
                              <-- IKE_AUTH response
authentication successful
HTTP request (cleartext)
install SAs and policies (1)

Then during the reauthentication this:

IKE_SA_INIT request -->
                              <-- IKE_SA_INIT response
IKE_AUTH request -->              
                                  authentication successful
                                  install SAs and policies (2)
                              <-- IKE_AUTH response
authentication successful
HTTP request using SA (1) -->
                                  forward/NAT HTTP request
                              <-- send back response using SA (2)
timeout while waiting for
response as it can't be
decrypted because SA (2)
is not yet installed, and
since the attestation failed
it never will, so the
connection is broken afterwards
due to the asymmetric SAs and
policies

As mentioned before you can avoid this by installing passthrough policies that allow the client to reach the HTTP server directly without going through the IPsec tunnel.

#8 Updated by Tao Su about 7 years ago

Hi, sorry for the late reply.

As mentioned before you can avoid this by installing passthrough policies that allow the client to reach the HTTP server directly without going through the IPsec tunnel.

I added a new conn with type passthrough in the client machine, trying to let the client machine to be reachable to the HTTP server directly. Here is the configuration of the client machine.

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
    # strictcrlpolicy=yes
        # uniqueids = no

# Add connections here.

conn pass
     leftid=userterminal2
     rightsubnet=192.168.1.86 
# this is the ip address of the http server
     authby=never
     type=passthrough
     auto=route

conn test-ned
#     ikelifetime=15s
     margintime=10s
#     rekey=yes
     leftid=userterminal2
     leftfirewall=yes
     leftsourceip = %config
     leftauth=psk
     right=192.168.1.110
     rightid="C=CH, O=strongSwan, CN=ned6" 
     rightsubnet = 0.0.0.0/0
     rightauth=pubkey
     auto=start

And here is the ipsec server side configuration:

# ipsec.conf - strongSwan IPsec configuration file

# basic configuration

config setup
    # strictcrlpolicy=yes
        # uniqueids = no

# Add connections here.

conn test-ned
     left=192.168.1.110
     leftid="C=CH, O=strongSwan, CN=ned6" 
     leftfirewall=yes
     leftauth=pubkey
     leftcert = peerCert.der
     leftsubnet=0.0.0.0/0
     right=%any
     rightsourceip = 10.1.0.0/24
     rightauth=psk
     rightsendcert=never
     auto=add

Before creating the conn pass, I followed the steps described in this this page https://wiki.strongswan.org/projects/strongswan/wiki/ForwardingAndSplitTunneling to set all the traffic from the client machine to go to the server through the ipsec tunnel, and the server will masquerade the traffic. The strange point is that, the ipsec tunnel will only work after I use the server to ping the client machine.

At this moment, after I created the conn pass, the ipsec tunnel is not working at all, the client machine cannot ping to anyone, and also the server side of the ipsec tunnel cannot ping to the client machine (with both the private ip or the public ip).

I am not fluent with strongswan, could you please pin point to me some test cases of how to set this passthrough policy that only the traffic to a specific ip address will not use the ipsec tunnel?

Thank you very much!

#9 Updated by Tobias Brunner about 7 years ago

The strange point is that, the ipsec tunnel will only work after I use the server to ping the client machine.

Sounds odd. You can try checking traffic counters (ipsec statusall or ip -s xfrm state) to see if packets from the client are sent via tunnel before pinging from the server.

At this moment, after I created the conn pass, the ipsec tunnel is not working at all, the client machine cannot ping to anyone, and also the server side of the ipsec tunnel cannot ping to the client machine (with both the private ip or the public ip).

You can check the installed policies in the kernel with ip xfrm policy. After starting the daemon you should see the passthrough policy there (plus some socket specific ones) - and due to auto=start the actual tunnel will also be initiated, so there could be more if that's successful.

I am not fluent with strongswan, could you please pin point to me some test cases of how to set this passthrough policy that only the traffic to a specific ip address will not use the ipsec tunnel?

ikev2/shunt-policies-nat-rw

#10 Updated by Tao Su about 7 years ago

Hi, I have tried the commands and compared the result with the shunt-policies-nat-rw example. I upload the details of the result in the attachment.

For the comparision with the previous test case, as you can see in the uploaded files, the result of ipsec statusall is common, and after the pass connection is created, the pass connection is loaded, but it is not used.

In all three scenarios, the output of ip -s xfrm state is the following:

src 192.168.1.71 dst 192.168.1.110
    proto esp spi 0xc7730223(3346203171) reqid 1(0x00000001) mode tunnel
Segmentation fault (core dumped)

And the output of ip xfrm policy, there are the policy for the pass connection.

src 192.168.1.0/24 dst 0.0.0.0/0 
    dir fwd priority 1443 ptype main 
src 192.168.1.0/24 dst 0.0.0.0/0 
    dir in priority 1443 ptype main 
src 0.0.0.0/0 dst 192.168.1.0/24 
    dir out priority 1443 ptype main 

But I still cannot ping to any node in the local network.

#11 Updated by Tobias Brunner about 7 years ago

For the comparision with the previous test case, as you can see in the uploaded files, the result of ipsec statusall is common, and after the pass connection is created, the pass connection is loaded, but it is not used.

Since the Linux kernel does not track traffic on policies (only on states) and such policies have no states associated with them, you won't see whether the passthrough connection is used or not. But if the SA to the server is established and you ping the HTTP server (covered by the passthrough policy) you should not see any increase in the traffic counters for that SA (unless there is other traffic, of course).

In all three scenarios, the output of ip -s xfrm state is the following:

src 192.168.1.71 dst 192.168.1.110
    proto esp spi 0xc7730223(3346203171) reqid 1(0x00000001) mode tunnel
Segmentation fault (core dumped)

I've never seen iproute2 segfault. Might indicate a general problem with your system/kernel.

But I still cannot ping to any node in the local network.

Check if the routes in routing table 220 are set up correctly (ip route list table 220). There should be one for the virtual IP and one for the passthrough policy.

#12 Updated by Tao Su about 7 years ago

Hi I have done another round of the testing, with two different client machines, one is running ubuntu 14.04 lts, with kernel version of 3.13.0-55-generic x86_64; another machine is running CentOS7 with kernel version of 3.10.0-229.7.2.el7.x86_64 (this if the one has the segmentation fault).

The strange point is that, the ipsec tunnel will only work after I use the server to ping the client machine.

Sounds odd. You can try checking traffic counters (ipsec statusall or ip -s xfrm state) to see if packets from the client are sent via tunnel before pinging from the server.

I checked traffic counter with ipsec statusall, it shows the packets are sent to the ipsec tunnel, but they are not forwarded to the intended destination.

However, in the server side, with ipsec statusall, it shows there is no traffic is coming from the tunnel.

After I pinged from the server, the counter shows the traffic starts coming from the ipsec tunnel. In the meantime, the counter in the client machine is reset to zero and starts to increase again.

For the comparision with the previous test case, as you can see in the uploaded files, the result of ipsec statusall is common, and after the pass connection is created, the pass connection is loaded, but it is not used.

Since the Linux kernel does not track traffic on policies (only on states) and such policies have no states associated with them, you won't see whether the passthrough connection is used or not. But if the SA to the server is established and you ping the HTTP server (covered by the passthrough policy) you should not see any increase in the traffic counters for that SA (unless there is other traffic, of course).

The counter shows that the traffic is still going through the ipsec tunnel when I am pinging the verifier (which should be covered by the passthrough policy).

In all three scenarios, the output of ip -s xfrm state is the following:
[...]

I've never seen iproute2 segfault. Might indicate a general problem with your system/kernel.

I agree with you, the CentOS7 machines all fail in this command.

But I still cannot ping to any node in the local network.

Check if the routes in routing table 220 are set up correctly (ip route list table 220). There should be one for the virtual IP and one for the passthrough policy.

The result of ip route list table 220 is empty. However, with ip route list, the output is:

default via 192.168.1.126 dev ens5 proto static metric 100
192.168.1.64/26 dev ens5 proto kernel scope lik src 192.168.1.71 metric 100

After the client machine can connect, I tried to use traceroute to the verifier, the result shows the traffic is still going through the ipsec server, so the passthrough policy is not affecting how the traffic are managed.

#13 Updated by Tao Su about 7 years ago

Hi, finally the passthrough policy works in the end.
I have to change the conn pass in ipsec.conf as following:

conn pass
    leftsubnet=192.168.1.71/32
    rightsubnet=192.168.1.86/32
    type=passthrough
    auto=route

But once I change the leftsubnet/rightsubnet to 192.168.1.0/26, the pass connection is not working again. The output of ip route list table 220 changes from

[root@userterminal strongswan-5.3.2]# ip route list table 220
default via 192.168.1.110 dev ens5  proto static  src 10.1.0.1
192.168.1.86 via 192.168.1.86 dev ens5  proto static  src 192.168.1.71

to
[root@userterminal strongswan-5.3.2]# nano /etc/strongswan/ipsec.conf
[root@userterminal strongswan-5.3.2]# ip route list table 220
default via 192.168.1.110 dev ens5  proto static  src 10.1.0.1

However, in the ikev2/shunt-policies-nat-rw, the test case works with the subnet option(i.e., leftsubnet=10.1.0.0/16).

#14 Updated by Tobias Brunner about 7 years ago

But once I change the leftsubnet/rightsubnet to 192.168.1.0/26, the pass connection is not working again. The output of ip route list table 220 changes from

[...]
to
[...]

You should see an error in the log when it fails in the second case. Could be that one of the lookups done to install the route fails (next hop etc.). How does the default routing table look like?

#15 Updated by Tao Su about 7 years ago

Tobias Brunner wrote:

But once I change the leftsubnet/rightsubnet to 192.168.1.0/26, the pass connection is not working again. The output of ip route list table 220 changes from

[...]
to
[...]

You should see an error in the log when it fails in the second case. Could be that one of the lookups done to install the route fails (next hop etc.). How does the default routing table look like?

There is no error in the log, it shows the pass shunt policy is successfully installed. I paste the log here:

root@tao-HP-EliteBook-850-G1:/usr/libexec/strongswan# ./starter --daemon charon --nofork
Starting strongSwan 5.3.2 IPsec [starter]...
00[DMN] Starting IKE charon daemon (strongSwan 5.3.2, Linux 3.13.0-55-generic, x86_64)
00[CFG] loading ca certificates from '/etc/strongswan/ipsec.d/cacerts'
00[CFG]   loaded ca certificate "C=CH, O=strongSwan, CN=strongSwan CA" from '/etc/strongswan/ipsec.d/cacerts/caCert-test-ned.der'
00[CFG]   loaded ca certificate "C=CH, O=strongSwan, CN=strongSwan CA" from '/etc/strongswan/ipsec.d/cacerts/caCert.der'
00[CFG] loading aa certificates from '/etc/strongswan/ipsec.d/aacerts'
00[CFG] loading ocsp signer certificates from '/etc/strongswan/ipsec.d/ocspcerts'
00[CFG] loading attribute certificates from '/etc/strongswan/ipsec.d/acerts'
00[CFG] loading crls from '/etc/strongswan/ipsec.d/crls'
00[CFG] loading secrets from '/etc/strongswan/ipsec.secrets'
00[CFG]   loaded IKE secret for %any
00[LIB] loaded plugins: charon aes des rc2 sha1 sha2 md5 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem fips-prf gmp xcbc cmac hmac soup attr kernel-netlink resolve socket-default stroke updown xauth-generic oat_attest
00[JOB] spawning 16 worker threads
charon (5542) started after 20 ms
06[CFG] received stroke: add connection 'test-ned'
06[CFG] left nor right host is our side, assuming left=local
06[CFG] added configuration 'test-ned'
07[CFG] received stroke: initiate 'test-ned'
07[IKE] initiating IKE_SA test-ned[1] to 192.168.1.110
07[ENC] generating IKE_SA_INIT request 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) N(HASH_ALG) ]
07[NET] sending packet: from 192.168.1.76[500] to 192.168.1.110[500] (724 bytes)
09[CFG] received stroke: add connection 'pass'
09[CFG] left nor right host is our side, assuming left=local
09[CFG] added configuration 'pass'
12[CFG] received stroke: route 'pass'
'pass' shunt PASS policy installed

14[NET] received packet: from 192.168.1.110[500] to 192.168.1.76[500] (481 bytes)
14[ENC] parsed IKE_SA_INIT response 0 [ SA KE No N(NATD_S_IP) N(NATD_D_IP) CERTREQ N(HASH_ALG) N(MULT_AUTH) ]
14[IKE] received cert request for "C=CH, O=strongSwan, CN=strongSwan CA" 
14[IKE] sending cert request for "C=CH, O=strongSwan, CN=strongSwan CA" 
14[IKE] sending cert request for "C=CH, O=strongSwan, CN=strongSwan CA" 
14[IKE] authentication of 'own' (myself) with pre-shared key
14[IKE] establishing CHILD_SA test-ned
14[ENC] generating IKE_AUTH request 1 [ IDi N(INIT_CONTACT) CERTREQ IDr AUTH CPRQ(ADDR DNS) SA TSi TSr N(MOBIKE_SUP) N(ADD_4_ADDR) N(MULT_AUTH) N(EAP_ONLY) ]
14[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (492 bytes)
04[NET] received packet: from 192.168.1.110[4500] to 192.168.1.76[4500] (1340 bytes)
04[ENC] parsed IKE_AUTH response 1 [ IDr CERT AUTH CPRP(ADDR) SA TSi TSr N(AUTH_LFT) N(MOBIKE_SUP) N(NO_ADD_ADDR) ]
04[IKE] received end entity cert "C=CH, O=strongSwan, CN=ned6" 
04[CFG]   using certificate "C=CH, O=strongSwan, CN=ned6" 
04[CFG]   using trusted ca certificate "C=CH, O=strongSwan, CN=strongSwan CA" 
04[CFG] checking certificate status of "C=CH, O=strongSwan, CN=ned6" 
04[CFG] certificate status is not available
04[CFG]   reached self-signed root ca with a path length of 0
04[IKE] authentication of 'C=CH, O=strongSwan, CN=ned6' with RSA_EMSA_PKCS1_SHA256 successful
04[LIB] 
04[LIB] 
04[LIB] ---------- Remote Attestation begins ----------
04[LIB] 
04[LIB] Extracted Common Name from peer certificate: ned6
04[LIB] SHA1 of the peer certificate: 295933e408f257333a458fbd6acf24b0443c016a
04[LIB] 
04[LIB] User terminal -> verifier:
04[LIB] request: { "hosts": [ "ned6" ], "analysisType": "load-time+check-cert,l_req=l1|>=,cert_digest=295933e408f257333a458fbd6acf24b0443c016a" }
04[LIB] 
04[LIB] Verifier -> user terminal:
04[LIB] response: {"hosts":[{"analysis_details":{"name":"load-time+check-cert","output":"","result":"true","status":"ANALYSIS_COMPLETED"},"host_name":"ned6","report_is_valid":"true","trust_lvl":"trusted","url":"http://verifier/OAT/report.php?id=524","vtime":"2015-06-29T11:32:50+02:00"}]}
04[LIB] 
04[LIB] Host: ned6, status: trusted
04[LIB] 
04[LIB] ---------- Remote Attestation ends ----------
04[LIB] 
04[LIB] 
04[IKE] IKE_SA test-ned[1] established between 192.168.1.76[own]...192.168.1.110[C=CH, O=strongSwan, CN=ned6]
04[IKE] scheduling reauthentication in 10788s
04[IKE] maximum IKE_SA lifetime 10798s
04[IKE] installing new virtual IP 10.1.0.2
04[IKE] CHILD_SA test-ned{1} established with SPIs ca8b8a58_i c1d219cf_o and TS 10.1.0.2/32 === 0.0.0.0/0 
04[IKE] received AUTH_LIFETIME of 3377s, scheduling reauthentication in 3367s
04[IKE] peer supports MOBIKE
^C00[DMN] signal of type SIGINT received. Shutting down
00[IKE] deleting IKE_SA test-ned[1] between 192.168.1.76[own]...192.168.1.110[C=CH, O=strongSwan, CN=ned6]
00[IKE] sending DELETE for IKE_SA test-ned[1]
00[ENC] generating INFORMATIONAL request 2 [ D ]
00[NET] sending packet: from 192.168.1.76[4500] to 192.168.1.110[4500] (76 bytes)
00[CFG] uninstalling shunt PASS 'policy pass' failed
charon stopped after 200 ms
ipsec starter stopped

Before creating the tunnel, the output of the ip route list is like:

default via 192.168.1.126 dev eth0  proto static 
192.168.1.64/26 dev eth0  proto kernel  scope link  src 192.168.1.76  metric 1 
192.168.122.0/24 dev virbr0  proto kernel  scope link  src 192.168.122.1 

After the tunnel is created, and the output is the same, as:

root@tao-HP-EliteBook-850-G1:/usr/libexec/strongswan# ip route
default via 192.168.1.126 dev eth0  proto static 
192.168.1.64/26 dev eth0  proto kernel  scope link  src 192.168.1.76  metric 1 
192.168.122.0/24 dev virbr0  proto kernel  scope link  src 192.168.122.1 

And the output of ipsec statusall is like:

root@tao-HP-EliteBook-850-G1:/usr/libexec/strongswan# ipsec statusall
Status of IKE charon daemon (strongSwan 5.3.2, Linux 3.13.0-55-generic, x86_64):
  uptime: 23 seconds, since Jun 29 11:51:15 2015
  malloc: sbrk 2965504, mmap 0, used 840240, free 2125264
  worker threads: 11 of 16 idle, 5/0/0/0 working, job queue: 0/0/0/0, scheduled: 3
  loaded plugins: charon aes des rc2 sha1 sha2 md5 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem fips-prf gmp xcbc cmac hmac soup attr kernel-netlink resolve socket-default stroke updown xauth-generic oat_attest
Listening IP addresses:
  192.168.1.76
  192.168.122.1
Connections:
    test-ned:  %any...192.168.1.110  IKEv2
    test-ned:   local:  [own] uses pre-shared key authentication
    test-ned:   remote: [C=CH, O=strongSwan, CN=ned6] uses public key authentication
    test-ned:   child:  dynamic === 0.0.0.0/0 TUNNEL
        pass:  %any...%any  IKEv2
        pass:   local:  uses public key authentication
        pass:   remote: uses public key authentication
        pass:   child:  192.168.1.64/26 === 192.168.1.64/26 PASS
Shunted Connections:
        pass:  192.168.1.64/26 === 192.168.1.64/26 PASS
Security Associations (1 up, 0 connecting):
    test-ned[1]: ESTABLISHED 19 seconds ago, 192.168.1.76[own]...192.168.1.110[C=CH, O=strongSwan, CN=ned6]
    test-ned[1]: IKEv2 SPIs: 8b1e739157207b33_i* 01325ca4e79eef79_r, pre-shared key reauthentication in 55 minutes
    test-ned[1]: IKE proposal: AES_CBC_128/HMAC_SHA1_96/PRF_HMAC_SHA1/MODP_2048
    test-ned{1}:  INSTALLED, TUNNEL, reqid 1, ESP SPIs: c02c89d4_i cb6a7655_o
    test-ned{1}:  AES_CBC_128/HMAC_SHA1_96, 0 bytes_i, 9776 bytes_o (158 pkts, 0s ago), rekeying in 59 minutes
    test-ned{1}:   10.1.0.2/32 === 0.0.0.0/0 

All previous commands are executed before the server ping to the client machine, so the client cannot let his traffic pass the ipsec tunnel. However, with leftsubnet=192.168.1.76/32 and rightsubnet=192.168.1.86/32, the traffic can reach the host of 192.168.1.86.

#16 Updated by Tobias Brunner about 7 years ago

What you posted seems to be from a different host (eth0 interface instead of ens5, and different IPs). Is the route in table 220 missing too?

There are several lookups needed to install the route:

  1. An IP in leftsubnet is searched. In this case 192.168.1.76 should be found.
  2. Then a next hop to reach rightsubnet is searched, which should return NULL as the host is directly connected to the subnet.
  3. Then the name of the interface on which 192.168.1.76 is installed is determined (eth0 here).

That should result in a route like 192.168.1.64/26 dev eth0 proto static src 192.168.1.76 getting installed in table 220. To see more of that process in the log you could increase the log level for the knl subsystem to 2 (I saw that route installation silently fails, i.e. without log messages on level 1, if step 1 or 3 fails).

#17 Updated by Tao Su about 7 years ago

Tobias Brunner wrote:

What you posted seems to be from a different host (eth0 interface instead of ens5, and different IPs). Is the route in table 220 missing too?

I have two machines for testing, just in case there are some problems with the kernel version instead of the software itself, e.g., the ip -s xfrm state does not work in the CentOS7 machine with kernel 3.10.0-229.7.2.

Strangely, with the same configuration file, like leftsubnet=192.168.1.76/26 and rightsubnet=192.168.1.86/26, this new machine works.

But if I change them to leftsubnet=192.168.1.0/26 and rightsubnet=192.168.1.0/26, this machine also fails to load the pass through connection.
And the output of ip route list table 220 is like:

default via 192.168.1.126 dev eth0  proto static  src 10.1.0.2 

There are several lookups needed to install the route:

  1. An IP in leftsubnet is searched. In this case 192.168.1.76 should be found.
  2. Then a next hop to reach rightsubnet is searched, which should return NULL as the host is directly connected to the subnet.
  3. Then the name of the interface on which 192.168.1.76 is installed is determined (eth0 here).

That should result in a route like 192.168.1.64/26 dev eth0 proto static src 192.168.1.76 getting installed in table 220. To see more of that process in the log you could increase the log level for the knl subsystem to 2 (I saw that route installation silently fails, i.e. without log messages on level 1, if step 1 or 3 fails).

I tried to increase the log level with ipsec.conf, I added a charondebug in the %default setting, here is the output log.

root@tao-HP-EliteBook-850-G1:/usr/libexec/strongswan# ./starter --daemon charon --nofork
Starting strongSwan 5.3.2 IPsec [starter]...
# unsupported keyword 'charondebug' in conn 'test-ned'
# ignored conn 'test-ned' due to 1 parsing error
# unsupported keyword 'charondebug' in conn 'pass'
# ignored conn 'pass' due to 1 parsing error
### 2 parsing errors (0 fatal) ###
00[DMN] Starting IKE charon daemon (strongSwan 5.3.2, Linux 3.13.0-55-generic, x86_64)
00[CFG] loading ca certificates from '/etc/strongswan/ipsec.d/cacerts'
00[CFG]   loaded ca certificate "C=CH, O=strongSwan, CN=strongSwan CA" from '/etc/strongswan/ipsec.d/cacerts/caCert-test-ned.der'
00[CFG]   loaded ca certificate "C=CH, O=strongSwan, CN=strongSwan CA" from '/etc/strongswan/ipsec.d/cacerts/caCert.der'
00[CFG] loading aa certificates from '/etc/strongswan/ipsec.d/aacerts'
00[CFG] loading ocsp signer certificates from '/etc/strongswan/ipsec.d/ocspcerts'
00[CFG] loading attribute certificates from '/etc/strongswan/ipsec.d/acerts'
00[CFG] loading crls from '/etc/strongswan/ipsec.d/crls'
00[CFG] loading secrets from '/etc/strongswan/ipsec.secrets'
00[CFG]   loaded IKE secret for %any
00[LIB] loaded plugins: charon aes des rc2 sha1 sha2 md5 random nonce x509 revocation constraints pubkey pkcs1 pkcs7 pkcs8 pkcs12 pgp dnskey sshkey pem fips-prf gmp xcbc cmac hmac soup attr kernel-netlink resolve socket-default stroke updown xauth-generic oat_attest
00[JOB] spawning 16 worker threads
charon (28699) started after 20 ms
^C00[DMN] signal of type SIGINT received. Shutting down
charon stopped after 200 ms
ipsec starter stopped

I also paste the ipsec.conf here:

 
config setup
        # strictcrlpolicy=yes
        # uniqueids = no

conn %default
     charondebug="ike 2, knl 3, cfg 0" 

conn test-ned
     rekeyfuzz=0%
     keyexchange =ikev2
#     ikelifetime=20s
#     margintime=10s
     rekey=yes
     leftid=own
     leftfirewall=yes
     leftsourceip = %config
     leftauth=psk
     right=192.168.1.110
     rightid="C=CH, O=strongSwan, CN=ned6" 
     rightsubnet =0.0.0.0/0
     rightauth=pubkey
     auto=start

conn pass
      keyexchange=ikev2
      leftsubnet=192.168.1.0/26
      rightsubnet=192.168.1.0/26
      authby=never
      type=pass
      auto=route

#18 Updated by Tobias Brunner about 7 years ago

Strangely, with the same configuration file, like leftsubnet=192.168.1.76/26 and rightsubnet=192.168.1.86/26, this new machine works.

But if I change them to leftsubnet=192.168.1.0/26 and rightsubnet=192.168.1.0/26, this machine also fails to load the pass through connection.
And the output of ip route list table 220 is like:

While 192.168.1.76/26 is the same subnet as 192.168.1.86/26 (i.e. 192.168.1.64/26), 192.168.1.0/26 is a different subnet (that does not include 192.168.1.86).

I tried to increase the log level with ipsec.conf, I added a charondebug in the %default setting, here is the output log.

You have to add it to the config setup section.

#19 Updated by Tao Su about 7 years ago

Tobias Brunner wrote:

Strangely, with the same configuration file, like leftsubnet=192.168.1.76/26 and rightsubnet=192.168.1.86/26, this new machine works.

But if I change them to leftsubnet=192.168.1.0/26 and rightsubnet=192.168.1.0/26, this machine also fails to load the pass through connection.
And the output of ip route list table 220 is like:

While 192.168.1.76/26 is the same subnet as 192.168.1.86/26 (i.e. 192.168.1.64/26), 192.168.1.0/26 is a different subnet (that does not include 192.168.1.86).

I tried to increase the log level with ipsec.conf, I added a charondebug in the %default setting, here is the output log.

You have to add it to the config setup section.

Silly me!

Right now the pass through connection is working. However, I still have a problem related to make-before-break option. In my understanding, if both the server and the client activate this option, the old IKE_SA and its correlated CHILD_SAs are kept alive until the new IKE_SA and its CHILD_SAs are installed. The output log agrees with the description.

The problem is, when I use the customised plugin, there is still a connection gap (with passthrough connection working) during the re-authentication interval. The traffic to the ipsec tunnel is stopped and re-started only after the attestation result is returned. During this interval, if I run ipsec statusall, there will be no output until the attestation finishes. Then there are two SAs in the output, the previous one is in 'deleting' status, the newer one is 'installed' status. Also the server side has two SAs installed at this point.

I think this is a problem of how the plugin hooks to the listener, it creates itself as 'authorize' type, so the new IKE_SA and its CHILD_SAs are not installed until this plugin gives back the 'TRUE' result.

My question is, if my understanding is correct, the make-before-break option is actually not working correctly, because the authorize listener can affect the old SAs as well as the new ones. So the connection gap is always there. Am I right or I mis-understand something here?

Thank you very much

#20 Updated by Tobias Brunner about 7 years ago

The problem is, when I use the customised plugin, there is still a connection gap (with passthrough connection working) during the re-authentication interval. The traffic to the ipsec tunnel is stopped and re-started only after the attestation result is returned.

That's because the responder uses the new CHILD_SA, while the initiator has not yet installed it (you can see this asymmetry in the diagram I posted above in #989-7).

During this interval, if I run ipsec statusall, there will be no output until the attestation finishes.

Yes, the IKE_SA is locked while it waits for the authorize() hook to finish (i.e. for the HTTP response). There is a non-blocking version of ipsec statusall (ipsec stroke statusall-nb) but that just skips locked SAs.

I think this is a problem of how the plugin hooks to the listener, it creates itself as 'authorize' type, so the new IKE_SA and its CHILD_SAs are not installed until this plugin gives back the 'TRUE' result.

Yes, that's correct. This is definitely one of the disadvantages of doing this outside of the IKEv2 exchange (with EAP-TNC the client is not authenticated if attestation fails, so there wouldn't be this problem as the responder wouldn't install the new CHILD_SAs). Another problem is that it's up to the client to actually terminate the SA if attestation fails (the responder can't enforce that unless it is informed by the attestation server about the failed attestation somehow), with EAP-TNC that's not the case as the responder acts as PEP.

My question is, if my understanding is correct, the make-before-break option is actually not working correctly, because the authorize listener can affect the old SAs as well as the new ones. So the connection gap is always there.

Yes, there probably will be a (short) gap. From the installation of the SA on the responder until the initiator receives the last IKE_AUTH message and it finally installs the SA itself (this is actually also the case for the initial SA, where the responder could send packets before the client is able to decrypt them). The main problem here is the delay in the authorize() hook, which is triggered in between receiving the IKE_AUTH response and installing the SAs (so this could also happen if CRL lookups take a while).

In your case I suppose you could also queue a job from the authorize hook and do the attestation asynchronously (after the CHILD_SA has been installed) and if it fails just delete the IKE_SA.

#21 Updated by Tao Su about 7 years ago

In your case I suppose you could also queue a job from the authorize hook and do the attestation asynchronously (after the CHILD_SA has been installed) and if it fails just delete the IKE_SA.

Hi, I am creating the queue job with a callback_job function, this is how I invoke it:

lib->processor->queue_job(lib->processor, (job_t*)callback_job_create(attest_request, hostdata, NULL, NULL));

hostdata is a self defined struct with three elements, like the following one:

typedef struct attest_data {
        char *host_name;
        char *cert_digest;
        int ike_sa_id;
} attest_data_t;

I initiate hostdata with the data extracted from the certificate and the ike id. It works fine before the hostdata is passed to the job, here is how I define the job:

static job_requeue_t attest_request(attest_data_t *this)
{
        printf("this is the host name %s\n\nthis is the cert digest\n\nthis is the ike id\n\n",this->host_name, this->cert_digest, this->ike_sa_id);
        return JOB_REQUEUE_NONE;
}

When I activate the charon daemon, the first two strings are always empty, but the ike_sa_id give back the value as it should.

For this reason, I have to pass the certificate directly to the job, and let it extracts the information for the host name and the certificate digest again. This approach works but the solution is not elegant.

May I ask if there is some errors for the callback_job to deal with the strings in the struct or it is my mistake to use the function in a wrong way?

Thank you very much!

#22 Updated by Tobias Brunner about 7 years ago

Hi, I am creating the queue job with a callback_job function, this is how I invoke it:

lib->processor->queue_job(lib->processor, (job_t*)callback_job_create(attest_request, hostdata, NULL, NULL));

You should also pass an appropriate cleanup function to the callback job constructor (third argument) so the memory is freed properly.

I initiate hostdata with the data extracted from the certificate and the ike id.

How exactly do you initialize that struct and its members?

For this reason, I have to pass the certificate directly to the job, and let it extracts the information for the host name and the certificate digest again. This approach works but the solution is not elegant.

This shouldn't really be a problem as long as you pass a reference to the certificate (get_ref) to the job (otherwise the pointer might not be valid anymore when accessing it in the job). You also need to destroy the object in the cleanup function.

#23 Updated by Tao Su about 7 years ago

Tobias Brunner wrote:

Hi, I am creating the queue job with a callback_job function, this is how I invoke it:
[...]

You should also pass an appropriate cleanup function to the callback job constructor (third argument) so the memory is freed properly.

I wrote a destroy function to free the strings in the attest_data_t struct.

I initiate hostdata with the data extracted from the certificate and the ike id.

How exactly do you initialize that struct and its members?

Right before calling the callback_job function, I initialise the struct as following:

INIT(hostdata, 
     .host_name = hostname, 
     .cert_digest = digest_str,
     .ike_sa_id = ike_sa->get_unique_id(ike_sa),
);

Before calling the callback_job function, the elements in this hostdata are correct, but once it is inputed into the job function, the host_name and the cert_digest strings are empty(while ike_sa_id is not).
For this reason, I cannot use the strings as the input of the attestation function.

#24 Updated by Tobias Brunner about 7 years ago

I initiate hostdata with the data extracted from the certificate and the ike id.

How exactly do you initialize that struct and its members?

Right before calling the callback_job function, I initialise the struct as following:

This looks OK. But how are the strings allocated? Are they manipulated (freed, modified) any further in the function doing the initialization?

Before calling the callback_job function, the elements in this hostdata are correct, but once it is inputed into the job function, the host_name and the cert_digest strings are empty(while ike_sa_id is not).

The SA ID is passed as value while the strings are passed as pointers (you might have to strdup() them depending on the answers to the questions above).

#25 Updated by Tao Su about 7 years ago

Tobias Brunner wrote:

I initiate hostdata with the data extracted from the certificate and the ike id.

How exactly do you initialize that struct and its members?

Right before calling the callback_job function, I initialise the struct as following:

This looks OK. But how are the strings allocated? Are they manipulated (freed, modified) any further in the function doing the initialization?

Before calling the callback_job function, the elements in this hostdata are correct, but once it is inputed into the job function, the host_name and the cert_digest strings are empty(while ike_sa_id is not).

The SA ID is passed as value while the strings are passed as pointers (you might have to strdup() them depending on the answers to the questions above).

You are right, the reason that the elements are empty is because in the end of this listener, the hostname is freed, after I changed to strdup, it works like a charm!

Thank you very much!

#26 Updated by Tobias Brunner over 6 years ago

  • Status changed from Feedback to Closed
  • Assignee set to Tobias Brunner
  • Resolution set to No change required

Also available in: Atom PDF