Forum Discussion

AndOs's avatar
AndOs
Icon for Cirrostratus rankCirrostratus
Sep 22, 2012

Sporadic TCL erros from iRule after upgrade to 11.2.0

Hi!

We're using an irule to handle access to a webservice.

The irule matches the client certificate DN against a list of allowed DNs, and is the only irule assigned to the VIP.

After upgrading from v10.2.0 to 11.2.0 we're occasionally getting this error in /var/log/ltm

tmm err tmm[7146]: 01220001:3: TCL error: /Webservices/certificate_verify_irule - can't read "client_cert_ok": no such variable while executing "if {$client_cert_ok == 0} { HTTP::respond 403 content "Bad client certificate! ($subject_dn)" set client_cert_ok 0 }"

The error complains about not beeing able to read the variable client_cert_ok, but works most of the time.

Searching the forums I found this post (TCL Error:no such variable while executing)

The replies there talks about RULE_INIT, but in this case, putting client_cert_ok in RULE_INIT will make it global, right? And I need it to be "local" for each client.

Appreciate all tips on how to solve this.

I have a vague idea that it might be CMP related, but I'm not that skilled in irules to see if there's cmp issue with this one.

Thanks!

/Andreas

 Derived from https://devcentral.f5.com/wiki/default.aspx/iRules/ClientCertificateCNChecking.html

when RULE_INIT {
}

when CLIENTSSL_CLIENTCERT {

    init allowed/disallowed flag
    default not allowed.
   set client_cert_ok 0

    Check if client provided a cert
   if {[SSL::cert 0] eq ""} {

      log local0. "No client cert presented!"
       Reset the connection
      reject

   } else { 

       Get the subject DN from cert.
      set subject_dn [X509::subject [SSL::cert 0]]

       Check trusted certs.
      switch -glob [string tolower $subject_dn] {
          "...DN1..." -
          "...DN2..." {
                    Client cert is allowed. Set flag.
                   set client_cert_ok 1
                   log local0. "Matching client cert: $subject_dn | Client='[IP::client_addr]'"
            }
          default {
              log local0. "NO MATCHING CLIENT CERTIFICATE!: $subject_dn | Client='[IP::client_addr]'"
              reject
          }
      }
   }
}

when HTTP_REQUEST {

 Client sent an HTTP request.

     check if the client cert for this connection was trusted.
     if it was not, send an error message to the client.
    if {$client_cert_ok == 0} {
         HTTP::respond 403 content "Bad client certificate! ($subject_dn)"
         set client_cert_ok 0
    }
}

2 Replies

  • If the client resumes an existing SSL session, they wouldn't hit the CLIENTSSL_CLIENTCERT event as they don't present the cert for that connection. You could change your check in HTTP_REQUEST to verify the variable exists and is set to 1:

    
    when HTTP_REQUEST {
    
    if { [info exists client_cert_ok] and $client_cert_ok == 1 }{
     Allow request
    } else {
    HTTP::respond 403 content "Bad client certificate!"
    }
    }
    

    Aaron
  • AndOs's avatar
    AndOs
    Icon for Cirrostratus rankCirrostratus
    Ah, ok.

     

    Thanks.

     

     

    And to track a client trough multiple requests, I guess I need to use the session table to keep it compatlible with CMP?

     

     

     

    /Andreas