Forum Discussion

dctechs_180672's avatar
dctechs_180672
Icon for Nimbostratus rankNimbostratus
May 11, 2015

"SSL::cert mode require" does not work

I'm trying to use an iRule to perform client certificate authentication on certain parts of my website and not others. I found this article to use a starting point: https://devcentral.f5.com/articles/selective-client-cert-authentication

 

Everything seems to work except for the "SSL::cert mode require" line. The browser (and a packet capture confirms it) never receives a request from the F5 for its client certificate. The ltm log shows the following after a failure:

 

May 11 14:13:06 4000s-1 info tmm[15688]: Rule /Common/test-by-uri-cert-auth : Protected URI requested: /protected/index.htm May 11 14:13:06 4000s-1 info tmm[15688]: Rule /Common/test-by-uri-cert-auth : No Certificate Provided

 

The iRule is:

 

when HTTP_REQUEST { if { [HTTP::uri] starts_with "/protected/" } { log local0. "Protected URI requested: [HTTP::uri]" if { [SSL::cert count] <=0 } { HTTP::collect SSL::authenticate always SSL::authenticate depth 9 SSL::cert mode require SSL::renegotiate } } }

 

when CLIENTSSL_CLIENTCERT { HTTP::release

 

if { [SSL::cert count] < 1 } { log local0. "No Certificate Provided" reject } }

 

4 Replies

  • All defaults except for the Trusted and Advertised CAs. If I set Client Certificate to "request" in the SSL profile then the browser starts complaining about "ERR_SSL_VERSION_OR_CIPHER_MISMATCH" (chrome) or "Turn on TLS 1.0, TLS 1.1, and TLS 1.2 in Advanced settings and try connecting... again" (IE).
  • Problem solved. Setting Client Certificate to "request" in the SSL client profile was the right move. Once I resolved the browser errors (which were totally misleading) everything started working as expected. I still don't understand why "ignore" seems to overwrite the "SSL::cert mode require" statement in the iRule.

     

    As for the browser errors, they were entirely misleading. I discovered in the log this error which led me to the real solution: - Illegal argument. Can't execute in the current context. (line 1) invoked from within "HTTP::release "

     

    In some cases my iRule was trying to run HTTP::release when HTTP::collect had never run. I solved that problem by just tracking when HTTP::collect was run and only running HTTP::release in those cases.

     

    The working iRule is:

     

    when CLIENT_ACCEPTED { set collected 0 }

     

    when HTTP_REQUEST { if { [HTTP::uri] starts_with "/protected/" } { log local0. "Protected URI requested: [HTTP::uri]" if { [SSL::cert count] <=0 } { set collected 1 HTTP::collect SSL::authenticate always SSL::authenticate depth 9 SSL::cert mode require SSL::renegotiate } } }

     

    when CLIENTSSL_CLIENTCERT { if { $collected eq 1 } { HTTP::release } if { [SSL::cert count] < 1 } { log local0. "No Certificate Provided" reject } }

     

    • dctechs_180672's avatar
      dctechs_180672
      Icon for Nimbostratus rankNimbostratus
      Another update: With the change to "request" I needed to make sure un-protected URIs didn't get rejected during CLIENTSSL_CLIENTCERT so I added an if statement to only check for a certificate for protected URIs (tracked by the $protected variable). when CLIENT_ACCEPTED { set collected 0 set protected 0 } when HTTP_REQUEST { if { [HTTP::uri] starts_with "/protected/" } { set protected 1 log local0. "Protected URI requested: [HTTP::uri]" set collected 1 HTTP::collect SSL::authenticate always SSL::authenticate depth 9 SSL::cert mode require SSL::renegotiate } } when CLIENTSSL_CLIENTCERT { if { $collected eq 1 } { log local0. "HTTP release" HTTP::release } if { $protected eq 1 } { if { [SSL::cert count] < 1 } { log local0. "No Certificate Provided" reject } else { log local0. "Certificate Provided!" if { [class match [X509::serial_number [SSL::cert 0]] equals test-serial-num-list] } { log local0. "Client Accepted - IP:[IP::client_addr] Serial:[X509::serial_number [SSL::cert 0]]" accept client cert } else { log local0. "Client Rejected -IP:[IP::client_addr] Serial:[X509::serial_number [SSL::cert 0]]" reject } } } }