Forum Discussion

James_Thomson's avatar
Dec 13, 2004

Inserting client certificate information into HTTP headers

To accomplish this, from reading the manual, it looks like I want to be using this:

 

 

SSL::modssl_sessionid_headers

 

and then

 

HTTP::header insert_modssl_fields

 

 

I'm having trouble formulating the whole thing. Do I need to specify in the rule to trigger the mod ssl feature and then insert on the way to the client? Or, can I just put a rule on the serverside that just uses certain fields.

 

 

Example, I'm not sure if I need to do this,

 

when CLIENTSSL_CLIENTCERT {

 

SSL::modssl_sessionid_headers

 

}

 

 

before I actually do the inserting, or if I can do them in one step?

 

 

when HTTP_REQUEST {

 

HTTP::header insert_modssl_fields

 

}

 

 

This will really help integration with Netegrity Siteminder since they have an agent now that plugs into the web server agent that can accept client certificate data in the form of http headers and authorize users. Thanks in advanace.

 

  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    It depends on the information you want to insert.

    If you just want the SessionId, then you can use something like the following:

     
     when HTTP_REQUEST { 
        HTTP::header insert [SSL::modssl_sessionid_headers] 
     } 
     

    If you are interested in more of the certificate information, then you will need to additionally use some of the X509:: commands. For example, you may want to do something like the following:

     
     when CLIENTSSL_HANDSHAKE { 
        set my_cert_0 [SSL::cert 0] 
        set my_verify_result [SSL::verify_result] 
     } 
     when HTTP_REQUEST { 
        HTTP::header insert [X509::cert_fields $my_cert_0 $my_verify_result versionnum serial sigalg issuer validity subject subpubkey hash] 
     } 
     

    You can, of course, use a smaller subset of the X509::cert_fields.

  • unRuleY_95363's avatar
    unRuleY_95363
    Historic F5 Account
    You can also try the following:

     
     when CLIENTSSL_HANDSHAKE { 
        set my_cert_0 [SSL::cert 0] 
        set my_verify_result [SSL::verify_result] 
     } 
     when HTTP_REQUEST { 
        HTTP::header insert [X509::cert_fields $my_cert_0 $my_verify_result whole] 
     } 
     
  • bl0ndie_127134's avatar
    bl0ndie_127134
    Historic F5 Account

    There is an open issue with using the 'whole' option and will be fixed on the next release. You can track the issue using CR43015. You can work around this by hand rolling the header insert in the following way.

     
     when HTTP_REQUEST {  
         set my_cert_0 [SSL::cert 0]  
         HTTP::header insert SSLClientCert [b64encode $my_cert_0] 
     }
  • when CLIENTSSL_HANDSHAKE {

     

    set my_cert_0 [SSL::cert 0]

     

    set my_verify_result [SSL::verify_result]

     

    }

     

     

    when HTTP_REQUEST {

     

    HTTP::header insert [X509::cert_fields $my_cert_0 $my_verify_result issuer]

     

    }

     

     

    Using this rule, it seems to work except this is the only http header I get inserted:

     

     

    HTTP_SSLCLIENTCERTSTATUS:error number 1

     

     

    Looking at mod_ssl verify results error codes, I can't seem to see what a 1 would mean. 0 seems to be a pass:

     

    http://www.hmug.org/man/1/verify.html

     

     

    I'm using BIG-IP too already verify the client certificate against a CRL And that is working fine.

     

  • bl0ndie_127134's avatar
    bl0ndie_127134
    Historic F5 Account
    You should be able to get a little bit more information using the following rule.

      
      
     X509::verify_cert_error_string $error 
  • I used this and it worked great. This grabs the whole certificate, b64 encodes it and then passes it back to the server in an HTTP header. This is a little confusing because IE for some reason opens up two connections during an ssl handshake. This rule basically takes the certificate from the first connection and carries it over to the second connection by inserting it into a cookie:

     
     rule insertcerthdr_long { 
        when RULE_INIT { 
       set ::key [AES::key 128] 
       log local0. "the key is:  $::key" 
     } 
      
     when CLIENTSSL_CLIENTCERT { 
      session add ssl [SSL::sessionid] [X509::verify_cert_error_string [SSL::verify_result]] 180 
      session add ssl [SSL::sessionid] [SSL::cert 0] 180 
     } 
      
     when HTTP_REQUEST { 
       if {! [HTTP::cookie exists ClientZ]} { 
          set id [SSL::sessionid] 
          set cert [session lookup ssl $id] 
          if { $cert ne "" } { 
            log "cert is:  $cert" 
            session delete ssl $id 
          } else { 
            log "no cert, no connection!" 
            reject 
            return 
          } 
          set z [b64encode [AES::encrypt $::key $cert]] 
       } else { 
          set cert [AES::decrypt $::key [b64decode [HTTP::cookie ClientZ]]] 
       } 
       HTTP::header insert ClientCert [b64encode $cert] 
       log "Inserting HTTP header ClientCert: $cert" 
     } 
      
     when HTTP_RESPONSE { 
       if { [info exists z ]} { 
         log "in http response Z is: $z" 
         HTTP::header insert "Set-Cookie ClientZ=$z" 
       } 
     } 
     } 
     

  • G__Wesley_Rober's avatar
    G__Wesley_Rober
    Historic F5 Account
    I have a client using this same iRule. With production traffic, the session table rarely shows more that 1-2 records. Observing the session table during test traffic with two clients we can see the same record getting updated (as evidenced by the idle timer updating) by browser activity from either client, and therefore the server is often seeing the cert for the wrong client in the header. Logging of the sessionid shows they are nearly always the same value. The ID logged doesn’t match the ID in the session table either. I think there is a problem with the [SSL::sessionid] command returning bogus (always the same) values. I also think there is a problem with the output of either the logged sessionid value or the session table output.

    We are dumping the session table with:

    “b persist mode ssl show all”

    TROUBLESHOOTING STEPS TAKEN

    Using a very simple version of an iRule from DevCentral and SOL 5171, we have encountered the same issue in the test environment. Here is the Wiki documentation of the methodology they are using:

    http://devcentral.f5.com/wiki/default.aspx/iRules/session.html

    Here is a copy of the test iRule we implemented, posted here: http://devcentral.f5.com/Default.aspx?tabid=53&view=topic&forumid=5&postid=3469 .

    
    when CLIENTSSL_HANDSHAKE
    {
      set cur [SSL::sessionid]
      set ask [session lookup ssl $cur] 
      if { $ask eq "" } { 
      session add ssl [SSL::sessionid] [SSL::cert 0]}
    }
    
    when HTTP_REQUEST
    {
      set id [SSL::sessionid]
      set the_cert [session lookup ssl $id]
      if { $the_cert != ""}
      {
        HTTP::header replace SSLClientCert [b64encode $the_cert]
      }
    }
    

    They have opened a support case, but was wondering why others aren't seeing similar issues.

    TIA,

    Wes