08-Sep-2016 11:01
We're performing client mutual authentication on a few of our sites and we want to verify that the cert being presented by the client hasn't been revoked. We're using OCSP profiles to do this but we're running into a problem in our testing. I've setup an OCSP responder for each of the CAs that we support (Verisign, DigiCert, Entrust, GoDaddy, Thawte, etc...). I then created a configuration profile and assigned that configuration profile to the 'ssl_ocsp' authentication profile.
The problem, the F5 always queries the first OCSP responder in the configuration profile even if that isn't the responder for the CA that signed the certificate. Thoughts?
08-Sep-2016
15:41
- last edited on
05-Jun-2023
22:48
by
JimmyPackets
Let me preface what I'm about to provide with the following statements.
The OCSP functions that you see there in LTM are a remnant of a long-deprecated feature module called "Advanced Client Authentication" (ACA). ACA is the predecessor to Access Policy Manager (APM), and it's reasonable to assume that this ACA functionality will eventually also be removed.
ACA uses PAM in the management plane to control the various authentication functions, which means it generally doesn't call very well.
APM can do what you're asking for WAAAAAAAAAAYYYYYYYY easier...
But if this doesn't dissuade you, here is what you'd have to do to make it work with LTM OCSP. I haven't done it in a while, so some of the details may be a bit off. You'll first notice that the corresponding authentication profile mentions an iRule, and indeed ACA auth functions are driven by iRules. Here are the steps you'll need to perform:
Create a single OCSP auth responder-config-profile set. This will create a text file under /config/bigip/auth/pam.d. I created a set called "ocsp-test" and it created a symlinked file called
tmm_commonocsptest1
that points to
/config/bigip/auth/pam.d/AuthConfigs/Common/pam_ocsp_ocsp-test
Make as many copies as necessary of the text file and symlink and give each a separate name.
Edit each text file and replace the "-url" and "-CAfile" data with the correct information for a given resource. If the responder signs the response with a CA-issued certificate (delegated trust model), you should only need the -url and -CAfile options. If the responder certificate is self-signed, or does not an Enhanced Key Usage of OCSP Signing (1.3.6.1.5.5.7.3.9), you should also use the -VAfile option to include the responder's certificate.
In the GUI, create a data group. For this example we'll call it "ocsp_server_list", of type string.
For each OCSP resource, use the lowercase common name value of the issuer as a string (ex symantec ca-12) for the data group key, and use the corresponding symlink OCSP profile name (ex. tmm_commonocsptest1) as the data group value.
Create a new version of the **_sys_auth_ssl_ocsp** iRule and make the following changes:
when CLIENT_ACCEPTED {
set tmm_auth_ssl_ocsp_sid 0
set tmm_auth_ssl_ocsp_done 0
}
when CLIENTSSL_CLIENTCERT {
if {[SSL::cert count] == 0} {
return
}
set tmm_auth_ssl_ocsp_done 0
if {$tmm_auth_ssl_ocsp_sid == 0} {
Get the issuer
set thisissuer [string tolower [findstr [X509::issuer [SSL::ce rt 0]] "CN=" 3 ","]]
look up the issuer in the ocsp_server_list datagroup
if { [class lookup $thisissuer ocsp_server_list] ne "" } {
set tmm_auth_ssl_ocsp_sid [AUTH::start pam [class lookup $thisissuer ocsp_server_list]]
} else {
set tmm_auth_ssl_ocsp_sid [AUTH::start pam default_ssl_ocsp]
}
if {[info exists tmm_auth_subscription]} {
AUTH::subscribe $tmm_auth_ssl_ocsp_sid
}
}
AUTH::cert_credential $tmm_auth_ssl_ocsp_sid [SSL::cert 0]
AUTH::cert_issuer_credential $tmm_auth_ssl_ocsp_sid [SSL::cert issuer 0]
AUTH::authenticate $tmm_auth_ssl_ocsp_sid
SSL::handshake hold
}
when CLIENTSSL_HANDSHAKE {
set tmm_auth_ssl_ocsp_done 1
}
when AUTH_RESULT {
if {[info exists tmm_auth_ssl_ocsp_sid] and ($tmm_auth_ssl_ocsp_sid == [AUTH::last_event_session_id])} {
set tmm_auth_status [AUTH::status]
if {$tmm_auth_status == 0} {
set tmm_auth_ssl_ocsp_done 1
SSL::handshake resume
} elseif {$tmm_auth_status != -1 || $tmm_auth_ssl_ocsp_done == 0} {
reject
}
}
}
Apply this new iRule to your OCSP profile and test.
Like I said, I haven't tested this in a while, but it should work. In any case, you're probably far better off doing this in a more supported fashion with APM.
09-Sep-2016 07:59
In APM, client side authentication objects are typically called "AAA agents". You'll see in the Access menu, under AAA, several client side auth types, including OCSP. In this case you'd create a separate OCSP AAA agent for each CA. Then in the visual policy, after you've collected the client cert, add an Empty agent and apply logic in the branch rules to switch between the OCSP Auth agents based on the issuer of the client's cert.
09-Sep-2016 17:18
The certificate issuer field (a DN) should be unique across the various issuing CAs. You just have to find some attribute of that DN you can use to build your conditions. The first thing you should do is grab a sample of each and compare them.
09-Sep-2016 18:45
Session.ssl.cert.issuer is a variable that contains the CA used to authenticate the client cert. you can then look for some unique attribute within the DN by saying 'contains' followed by the attribute that makes that root CA unique such as the issuer name for example. Does that pretty much sum it up?
session.ssl.cert.issuer is the DN value of the immediate issuer of the subject of the client certificate, and is contained within the certificate itself. It doesn't really have as much to do with "authentication" as it does just "issuance" and chain of trust. In any case, this value is a DN, and each public issuing CA (Verisign, DigiCert, Entrust, GoDaddy, Thawte, etc.) should have a unique-enough DN string to be able to distinguish it from other issuers.
But I'd also point out that you're not going to see the "root" CA of any of these public CAs in any of the client certificates. As a matter of good security practice, public CAs issue subordinate CAs to do all of the heavy lifting, and in some cases there are multiple levels of subordinate CAs in a public CA's "chain". What you're going to see in the client's certificate is the issuer of that certificate, which may be one of several subordinate CAs of GoDaddy, for example). You're going to need to get samples of as many of these issuers as you can to help define your search patterns.