Forum Discussion

joris_46354's avatar
joris_46354
Icon for Nimbostratus rankNimbostratus
Dec 04, 2008

Irule SSL renegotiate well done?

Dear F5 irule specialists,

 

 

I created an irule to do an ssl renegotiation acquiring a client certificate when a certain http request is received on the WAF. I would like to share this code with you and I hope to get some useful feedback (well done or not? What could I improve?)

 

 

Here she comes;

 

 

 

when CLIENTSSL_CLIENTCERT {

 

set session_timeout 7200

 

log local0. "Clientssl handshake. Cert count: [SSL::cert count]"

 

 

if {[SSL::cert count] !=0 } {

 

set dn [X509::subject [SSL::cert 0]]

 

set ssl_status [X509::verify_cert_error_string [SSL::verify_result]]

 

if { $ssl_status eq "ok"} {

 

log local0. "Certificate validation OK (status $ssl_status). Client cert dn:

 

$dn"

 

set ssl_cert [SSL::cert 0]

 

set mysslid [SSL::sessionid]

 

log local0. "saving sslid in session $mysslid"

 

session add ssl [SSL::sessionid] $ssl_cert $session_timeout

 

}

 

else {

 

log local0. "Certificate validation NOT ok. Status: $ssl_status. Client cert

 

dn: $dn"

 

reject

 

session delete ssl [SSL::sessionid]

 

session delete uie redirtopost

 

SSL::session invalidate

 

}

 

}

 

}

 

 

when HTTP_REQUEST {

 

set request [HTTP::request]

 

log local0. "HTTP method: [HTTP::method], HTTP REQ: [HTTP::uri]"

 

if { [HTTP::uri] starts_with "/pkmslogin.form" and [HTTP::method] eq "POST"}{

 

log local0. "pkmslogin POST request detected"

 

SSL::cert mode require

 

SSL::authenticate always

 

SSL::authenticate depth 3

 

 

set sslid [SSL::sessionid]

 

log local0. "Lookup sslid in session: $sslid"

 

set the_cert [session lookup ssl $sslid]

 

 

if { $the_cert == "" } {

 

log local0. "In HTTP_REQUEST: Cert is empty. Collecting data"

 

set content_length [HTTP::header "Content-Length"]

 

HTTP::collect $content_length

 

 

if {[HTTP::payload] contains "login-form-type=cert"} {

 

log local0. "login-form-type cert detected. Renegotiating SSL"

 

SSL::renegotiate

 

session add uie redirtopost 1

 

}

 

}

 

else {

 

set b64crt [b64encode $the_cert]

 

regsub -all {=} $b64crt %3D b64crt

 

regsub -all {/} $b64crt %2F b64crt

 

regsub -all {\+} $b64crt %2B b64crt

 

set clientcertdn [X509::subject $the_cert]

 

set clientcertdnd "dummy"

 

set cadn [X509::issuer $the_cert]

 

set cadnd "dummy"

 

set n1 "username= \"company.dtd\">"

 

set n2 ""

 

set n3 ""

 

set n4 "&password=nopwd&login-form-type=pwd"

 

set newpayload [concat $n1$b64crt$n2$clientcertdnd$n3$cadnd$n4]

 

set payloadlen [string length $newpayload]

 

log local0. "-> In HTTP_REQUEST. We have a certificate. NOW POST IT. New payload

 

length is $payloadlen"

 

HTTP::payload replace 0 [HTTP::payload length] $newpayload

 

HTTP::release

 

}

 

}

 

}

 

 

when HTTP_RESPONSE {

 

if {[session lookup uie redirtopost] == "1"} {

 

log local0. "HTTP RESPONSE DETECTED REDIRTOPOST IN SESSION. Redirecting."

 

session add uie redirtopost 0

 

HTTP::respond 200 content {

 

 

 

method=post action="/pkmslogin.form" id="isabellogon">

 

 

 

 

 

}

 

 

}

 

}

 

 

 

 

A question I currently have with above code is that at the time the renogiation happens (when CLIENTSSL_CLIENTCERT) and a certificate is found, it looks like the initial request is not sent towards the backend server (That's why I added the when HTTP_RESPONSE code to force a redirect). I want to make sure that when the CLIENTSSL_CLIENTCERT finishes, the initial request is sent towards the backend.

 

 

 

Any comments are welcome!

 

 

 

No RepliesBe the first to reply