cURL / Mailing Lists / curl-library / Single Mail

curl-library

[Bug] HTTP header splitting in curl for PHP

From: Gabriel Totoliciu <gabriel.totoliciu_at_ddsec.net>
Date: Tue, 8 Mar 2011 22:33:02 +0200

Hello

(I'm not sure if this is the correct mailing list for curl for php bug
reports.
Please advise with the proper mailing list if this is the wrong one.)

I noticed a problem with the CURLOPT_HTTPHEADER option in PHP.
The php manual says the following:

"CURLOPT_HTTPHEADER
An array of HTTP header fields to set, in the format array('Content-type:
text/plain', 'Content-length: 100')"

Inserting CRLF into a header value splits the header into different headers.
This behavior seems to be a potential security problem.
It also does not comply to the RFC2616 section 2.2
(http://tools.ietf.org/html/rfc2616#section-2.2).

The RFC2616 section "2.2. Basic Rules" states the following:
"HTTP/1.1 defines the sequence CR LF as the end-of-line marker for all
   protocol elements except the entity-body (see appendix 19.3 for
   tolerant applications)."

"HTTP/1.1 header field values can be folded onto multiple lines if the
   continuation line begins with a space or horizontal tab."

"
CR = <US-ASCII CR, carriage return (13)>
 LF = <US-ASCII LF, linefeed (10)>
 SP = <US-ASCII SP, space (32)>
"

The follwing code should only send 2 headers:
Custom-header
Custom-header4

The problem is that it actually sends 3 headers:
Custom-header
Custom-header3
Custom-header4

Test code:
<?php
$c = curl_init();
curl_setopt($c, CURLOPT_URL, "http://example.com");
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_HTTPHEADER, array(
        "Custom-header: custom value\r\n Custom-header2:custom value
2\r\nCustomHeader3:custom value 3",
        "Custom-header4: custom value 4"
        ));

$res = curl_exec($c);
curl_close($c);
var_dump(json_decode($res));
?>

Sent headers:
array(3) {
  ["Custom-header"]=>
  string(42) "custom value Custom-header2:custom value 2"
  ["CustomHeader3"]=>
  string(14) "custom value 3"
  ["Custom-header4"]=>
  string(14) "custom value 4"
}

Expected behavior:
Since curl for php allows the programmer to give an *array of headers* as
the CURLOPT_HTTPHEADER parameter,
it should convert the CRLF characters to either CRLFSP or SP according to
the RFC.
This way, any encountered CRLF characters would not split the header value
into different headers,
as shown in the expected output headers below.

Changing the CRLF to CRLFSP in the previous code example gives an expected
output (only 2 headers) as shown below:

Corrected header string:
"Custom-header: custom value\r\n Custom-header2:custom value 2\r\n
CustomHeader3:custom value 3"

Expected output headers:

array(2) {
  ["Custom-header"]=>
  string(71) "custom value Custom-header2:custom value 2
CustomHeader3:custom value 3"
  ["Custom-header4"]=>
  string(14) "custom value 4"
}

Notice that by using CRLFSP (\r\n*SPACE*), the server interprets the text
following CRLFSP
as the continuation of the header value, according to the RFC.

Possible fixes:
Curl should handle this automatically (by replacing any CRLF with CRLFSP),
since it's an array of individual headers and not a string of headers.
This should be done because progammers naturally expect that a header value
does not split the header into multiple headers.

The best solution would be to allow programmers to give a key=>value array,
such as the one below:

curl_setopt($c, CURLOPT_HTTPHEADER, array(
        "Custom-header" => "custom value\r\n Custom-header2:custom value
2\r\nCustomHeader3:custom value 3",
        "Custom-header4" => "custom value 4"
        ));

This array format along with the CRLF correction would be an ideal behavior
for CURL for PHP.

Thank you for your time,
Gabriel Totoliciu

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2011-03-08