Forum Discussion

justin_westover's avatar
justin_westover
Icon for Nimbostratus rankNimbostratus
Sep 08, 2016

OCSP Responders and Configuration Profiles

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?

 

4 Replies

  • Let me preface what I'm about to provide with the following statements.

    1. 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.

    2. ACA uses PAM in the management plane to control the various authentication functions, which means it generally doesn't call very well.

    3. 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:

    1. 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
      
    2. Make as many copies as necessary of the text file and symlink and give each a separate name.

    3. 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.

    4. In the GUI, create a data group. For this example we'll call it "ocsp_server_list", of type string.

    5. 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.

    6. 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
              }
          }
      }
      
    7. 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.

  • 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.

     

  • 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.

     

  • 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.