Forum Discussion

Maxim_Taskov_90's avatar
Maxim_Taskov_90
Icon for Nimbostratus rankNimbostratus
Nov 15, 2011

Client Certificate Validation by Subject

I am trying to use the common name CN from the x509::subject variable to validate a client certificate. I used the rule from teh following post as a sample:

 

 

http://devcentral.f5.com/Community/GroupDetails/tabid/1082223/asg/39/aft/1167776/showtab/groupforums/Default.aspx

 

 

, and the following DevCentral Wiki for some additional ideas:

 

 

http://devcentral.f5.com/wiki/iRules.ClientCertificateCNChecking.ashx

 

 

My original iRule was:

 

 

when CLIENTSSL_CLIENTCERT {

 

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

 

log local0. "Client Certificate Received: $subject_dn"

 

if { [matchclass $subject_dn contains $::ebilling_accepted_certs]} {

 

log local0. "Client Certificate Accepted: $subject_dn"

 

} else {

 

log local0. "Invalid Client Certificate Was Found Using: $subject_dn"

 

reject

 

}

 

}

 

 

The above iRule does a very good job except that it had two defects, or at least that is what I observed in my deployment:

 

 

1. The iRule was crashing with TCL error when client certificate was not presented and instead of rejecting the connection, it allowed it.

 

 

2. The iRule was crashing with TCL error when the subject of client certificate was blank (yes, this happens) and instead of rejecting the connection, it allowed it.

 

 

Otherwise it was working very well by allowing the connectiong when the presented certificate was in the list of allowed and rejecting the connection when proper client certifiacte was presented (including a subject field, which is not blank) but it is not in the list of teh allowed certificates.

 

 

Then I tried to modify the rule to handle the failing conditions of 1 and 2 above. Here is what I got:

 

 

when CLIENTSSL_CLIENTCERT {

 

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

 

Log the subject properties of the presented certificate

 

log local0. "Client Certificate Received: $subject_dn"

 

Check to see if the presented certificate is allowed and if yes, accept

 

if {[matchclass $subject_dn contains $::ebilling_accepted_certs]} {

 

log local0. "Client Certificate Accepted: $subject_dn"

 

Check to see if certificate is presented and if not, reject

 

} elseif {[SSL::cert 0] eq ""} {

 

log local0. "Client Certificate was not provided"

 

reject

 

Check to see if the presented certificate has subject and if not, accept

 

} elseif {[string length $subject_dn] == 0 } {

 

log local0. "Client Certificate with blank subject was detected"

 

reject

 

} elseif {

 

Any other condition and valid bu unauthorized certificate, reject

 

log local0. "Unauthorized Client Certificate was detected: $subject_dn"

 

reject

 

}

 

}

 

 

The iRule above compiles and runs but still crashes and cannot handle the "blank subject" or "no certificate" conditions and continues to allow the connections when it should be rejecting them.

 

 

Any assistance will be greatly appreciated and is desperately needed. Thanks.
  • Nice work Nitass.

     

     

    Maxim, I think it's still important to escalate this to Support as X509::subject should return a null string if the subject in the cert is null or can't be parsed. And even if it does generate a runtime TCL error, that should trigger a reset of the TCP connection. So it's important for us to get the issue fixed.

     

     

    Aaron
  • Aaron,

     

     

    thanks! i agree with you. this could be escalated and get fixed.
  • Thanks for the test Nitass.

     

     

    I opened a case with F5 (F5 Case No. C998774). As usual they warned me that support is very limited but that they will log the case and see what the engineers will say. I will keep you posted.
  • Hoolio, nitass, this is what F5 Engineering Services delivered as a workaround but I can't make it compile yet, I am still tryng to figure out the logic:

     

     

    when CLIENTSSL_CLIENTCERT {

     

    if {[SSL::cert count] > 0}{

     

    set allfield "[X509::cert_fields [SSL::cert 0] [SSL::verify_result] issuer subject sigalg validity hash]"

     

    log local0. "$allfield"

     

    if { $allfield contains "SSLClientCertSubject" } {

     

    log local0. "matched SSLClientCertSubject"

     

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

     

    } else {

     

    log local0. "not matched SSLClientCertSubject"

     

    set subject_dn ""

     

    }

     

    log local0. "Client Certificate Received: $subject_dn"

     

    if {$subject_dn eq ""} {

     

    log local0. "Client Certificate with blank subject was detected"

     

    reject

     

    } elseif {[matchclass $subject_dn contains ebilling_accepted_certs]} {

     

    log local0. "Client Certificate Accepted: $subject_dn"

     

    } else {

     

    log local0. "Unauthorized Client Certificate was detected: $subject_dn"

     

    reject

     

    }

     

    }

     

    }

     

     

    Can you see a sytax error anywhere or is it the logic that is flawed?
  • spark_86682's avatar
    spark_86682
    Historic F5 Account
    You should continue with your support case, but if you urgently need a workaround, your best bet is likely to use the catch command to detect if the X509:: command errors out, and handle the error via the iRule.
  • hi Maxim,

    sorry i missed your message. i tested Engineering Service's irule and it seemed to be okay too.

    [root@ve1023:Active] iRuleTest  b virtual bar list
    virtual bar {
       snat automap
       pool foo
       destination 172.28.19.79:443
       ip protocol 6
       rules myrule
       profiles {
          http {}
          myclientssl {
             clientside
          }
          tcp {}
       }
    }
    [root@ve1023:Active] iRuleTest  b profile myclientssl list
    profile clientssl myclientssl {
       defaults from clientssl
       ca file "clientblank_ca.crt"
       peer cert mode require
    }
    [root@ve1023:Active] iRuleTest  b rule myrule list
    rule myrule {
       when CLIENTSSL_CLIENTCERT {
            if {[SSL::cert count] > 0}{
                    set allfield "[X509::cert_fields [SSL::cert 0] [SSL::verify_result] issuer subject sigalg validity hash]"
                    log local0. "$allfield"
                    if { $allfield contains "SSLClientCertSubject" } {
                            log local0. "matched SSLClientCertSubject"
                            set subject_dn [X509::subject [SSL::cert 0]]
                    } else {
                            log local0. "not matched SSLClientCertSubject"
                            set subject_dn ""
                    }
                    log local0. "Client Certificate Received: $subject_dn"
                    if {$subject_dn eq ""} {
                            log local0. "Client Certificate with blank subject was detected"
                            reject
                    } elseif {[matchclass $subject_dn contains ebilling_accepted_certs]} {
                            log local0. "Client Certificate Accepted: $subject_dn"
                    } else {
                            log local0. "Unauthorized Client Certificate was detected: $subject_dn"
                            reject
                    }
            }
    }
    }
    
    [root@ve1023:Active] iRuleTest  curl -ik https://172.28.19.79 --cert ./clientblank.crt --key ./clientblank.key
    curl: (55) SSL_write() returned SYSCALL, errno = 104
    
    [root@ve1023:Active] iRuleTest  
    Nov 28 20:22:26 local/tmm info tmm[23027]: Rule myrule : SSLClientCertStatus OK SSLClientCertIssuer {CN=Cartus Enrolment CA,DC=production,DC=cendantmobility,DC=net} SSLClientCertSignatureAlgorithm sha1WithRSAEncryption SSLClientCertNotValidBefore {Oct 23 20:55:00 2011 GMT} SSLClientCertNotValidAfter {Oct 22 20:55:00 2012 GMT} SSLClientCertHash e6:44:7e:d2:5e:6b:be:a0:e8:45:53:d2:17:0a:2d:ac
    Nov 28 20:22:26 local/tmm info tmm[23027]: Rule myrule : not matched SSLClientCertSubject
    Nov 28 20:22:26 local/tmm info tmm[23027]: Rule myrule : Client Certificate Received:
    Nov 28 20:22:26 local/tmm info tmm[23027]: Rule myrule : Client Certificate with blank subject was detected
    
    
  • Thank you nitass. Sorry for the delayed response but I was away for almost two weeks. Your latest update to the iRule works as desired. This solves my problem. I still don't know why Rule 1 below will not compile and Rule 2, the latest one in the above thread, compiles fine. I looked at them character by character and I still cannot see the difference, it has to be some space or special character somewhere that confuses the compiler as when it fails to compile, it fails with a long thread of error, which are usually indicative of a missing brace or bracket where the logic of the rule is completely incomprehensible to the compiler. Regardless the second rule works fine and that makes me happy.

     

     

    I also closed the F5 support case. Their last statement was that the DevCentral workaround should be the fix and that if I want to avoid the TCL bug and make my original rule work, I need to go to BIG-IP OS 10.2.1. I cannot do that at the present but I plan to do so in not so distant future.

     

     

    Thank you again for your timely and professional support. Regards, Maxim

     

     

    RULE 1

     

    ---------------------------------------

     

    when CLIENTSSL_CLIENTCERT {

     

    if {[SSL::cert count] > 0}{

     

    set allfield "[X509::cert_fields [SSL::cert 0] [SSL::verify_result] issuer subject sigalg validity hash]"

     

    log local0. "$allfield"

     

    if { $allfield contains "SSLClientCertSubject" } {

     

    log local0. "matched SSLClientCertSubject"

     

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

     

    }else{

     

    log local0. "not matched SSLClientCertSubject"

     

    set subject_dn ""

     

    }

     

    log local0. "Client Certificate Received: $subject_dn"

     

    if {$subject_dn eq ""} {

     

    log local0. "Client Certificate with blank subject was detected"

     

    reject

     

    }elseif{[matchclass $subject_dn contains ebilling_accepted_certs]} {

     

    log local0. "Client Certificate Accepted: $subject_dn"

     

    }else{

     

    log local0. "Unauthorized Client Certificate was detected: $subject_dn"

     

    reject

     

    }

     

    }

     

    }

     

     

     

    RULE 2

     

    ---------------------------------------

     

    when CLIENTSSL_CLIENTCERT {

     

    if {[SSL::cert count] > 0}{

     

    set allfield "[X509::cert_fields [SSL::cert 0] [SSL::verify_result] issuer subject sigalg validity hash]"

     

    log local0. "$allfield"

     

    if { $allfield contains "SSLClientCertSubject" } {

     

    log local0. "matched SSLClientCertSubject"

     

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

     

    } else {

     

    log local0. "not matched SSLClientCertSubject"

     

    set subject_dn ""}

     

    log local0. "Client Certificate Received: $subject_dn"

     

    if {$subject_dn eq ""} {

     

    log local0. "Client Certificate with blank subject was detected"

     

    reject

     

    } elseif {[matchclass $subject_dn contains ebilling_accepted_certs]} {

     

    log local0. "Client Certificate Accepted: $subject_dn"

     

    } else {

     

    log local0. "Unauthorized Client Certificate was detected: $subject_dn"

     

    reject

     

    }

     

    }

     

    }