Forum Discussion

Ichnafi's avatar
Ichnafi
Icon for Cirrostratus rankCirrostratus
Mar 07, 2016

Insert certificate in HTTP header fails, depending on what is logged

Hi,

I have stumbled upon a strange behavior. I insert a client certificate into the HTTP header. Nothing fancy. Then I wanted to add some DEBUG Messages to see what's happening. And here my confusion began:

Situation 1 (without DEBUG):

when HTTP_REQUEST {
Set DEBUG to 1 for Log-Messages
set DEBUG 0

 check if there is a SSL certificate available
    if { [SSL::cert count] > 0 } {

         insert this cert in PEM format to the (X-CLIENT-CERT) HTTP Header
        HTTP::header insert "X-CLIENT-CERT" "[X509::whole [SSL::cert 0]]"

        if { $DEBUG } {
            log local0. "Client inserted"
        }
    }
}

Result: Good! Certificate is inside the HTTP header. Wireshark shows:

Situation 2 (with DEBUG):

 when HTTP_REQUEST {
    Set DEBUG to 1 for Log-Messages
    set DEBUG 1

     check if there is a SSL certificate available
        if { [SSL::cert count] > 0 } {

             insert this cert in PEM format to the (X-CLIENT-CERT) HTTP Header
            HTTP::header insert "X-CLIENT-CERT" "[X509::whole [SSL::cert 0]]"

            if { $DEBUG } {
                log local0. "Client inserted"
            }
        }
    }

Result: Good! Certificate is inside the HTTP header. Wireshark shows:

Situation 3 (DEBUG and [HTTP::header names])

 when HTTP_REQUEST {
    Set DEBUG to 1 for Log-Messages
    set DEBUG 1

     check if there is a SSL certificate available
        if { [SSL::cert count] > 0 } {

             insert this cert in PEM format to the (X-CLIENT-CERT) HTTP Header
            HTTP::header insert "X-CLIENT-CERT" "[X509::whole [SSL::cert 0]]"

            if { $DEBUG } {
                log local0. "Client inserted"
                 let's see what headers we have
                log local0. [HTTP::header names]
            }
        }
    }

Result: The certificat is not present any more. The HTTP::header log-message shows every line of the certificate as a single header.

Wireshark:

Syslog:

Rule /Common/clientcert : Host User-Agent Accept Accept-Language Accept-Encoding DNT Connection X-Forwarded-Proto X-CLIENT-CERT: -----BEGIN CERTIFICATE-----   MIIFbzCCBFegAwIBAgIHApco8T/4CTANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQG   EwJERTEZMBcGA1UEChMQUEtJLTEtVmVyd2FsdHVuZzEMMAoGA1UECxMDRE9JMREw [...]

Am I getting something wrong here? Why is the Cert gone, when logging the HTTP headers?

7 Replies

  • Hi Ichnafi,

    the command

    [X509::whole [SSL::cert 0]]
    outputs multi-line text. Multi-line value can't be insert into a header without applying some encodings (e.g. Base64, Hex, URL-Encoding) to it. So I would recommend to wrap the certificate into B64 before setting the header and then use Base64 decoding on the server side to retrive the certificate.

    HTTP::header insert "X-CLIENT-CERT" [b64encode [X509::whole [SSL::cert 0]]]
    

    Cheers, Kai

  • Hello Kai,

     

    thanks for your reply. The client cert is already in Base64 PEM format, so why double encode it? Why should this brake the insertion, when applying the mentions log statements? Without "log local0. [HTTP::header names]", everything is fine, and the certificate is completely available under the header "X-CLIENT-CERT".

     

    • Kai_Wilke's avatar
      Kai_Wilke
      Icon for MVP rankMVP
      I know that the inner body of the cert is already encoded using B64. But the innner body includes also linebreaks that simply destroys your HTTP header. Thats why you have to use a second b64 layer or use URL-Encoding, HEX encoding, or even manually convert the PEM file format to become HTTP/1.1 compliant by inserting SP or HT characters in front of each new line (see RFC2616 4.2). But I guess just applying b64 or URL-Encoding is less complex... Cheers, Kai
    • Kai_Wilke's avatar
      Kai_Wilke
      Icon for MVP rankMVP
      Update: Just created a test scenario by inserting a whole cert into a header. It seems that [HTTP::header insert] already adds the required SP characaters in front of each line. But somehow the [HTTP::header names] command don't follow the RFCs and treat the multi-line value as independent headers. Well, its just the output of [HTTP::header names] that is wrong, but the format of the multi-line header ramains valid after [HTTP::header names] execution and should work for you as long as the backend application is following the RFCs. If the multi-line header still causes trouble on your backend application, then just use b64/URL-encodings to make the value less error phrone (aka. becomming a single-line to avoid edge cases)... Cheers, Kai
    • Kai_Wilke's avatar
      Kai_Wilke
      Icon for MVP rankMVP
      Note: Feel free to open a [HTTP::header names] bug report... ;-)