summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2018-12-17 15:46:56 +0100
committerDaniel Stenberg <daniel@haxx.se>2018-12-21 10:49:30 +0100
commit006ff62d8c51f664c167c6337f009f9f65dd8ea7 (patch)
treed3c28ede3f9a04053c3bcd5d2b2eb7cb5a191735
parentdb9776ea00226d1571e269464237b0d50191a0a3 (diff)
downloadcurl-006ff62d8c51f664c167c6337f009f9f65dd8ea7.tar.gz
http: added options for allowing HTTP/0.9 responses
Added CURLOPT_HTTP09_ALLOWED and --http0.9 for this purpose. For now, both the tool and library allow HTTP/0.9 by default. docs/DEPRECATE.md lays out the plan for when to reverse that default: 6 months after the 7.64.0 release. The options are added already now so that applications/scripts can start using them already now. Fixes #2873 Closes #3383
-rw-r--r--docs/DEPRECATE.md15
-rw-r--r--docs/cmdline-opts/Makefile.inc250
-rw-r--r--docs/cmdline-opts/http0.9.d14
-rw-r--r--docs/libcurl/curl_easy_setopt.32
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.358
-rw-r--r--docs/libcurl/opts/CURLOPT_HTTP_VERSION.31
-rw-r--r--docs/libcurl/opts/Makefile.inc5
-rw-r--r--docs/libcurl/symbols-in-versions1
-rw-r--r--include/curl/curl.h3
-rw-r--r--lib/http.c8
-rw-r--r--lib/setopt.c6
-rw-r--r--lib/url.c1
-rw-r--r--lib/urldata.h1
-rw-r--r--src/tool_cfgable.c1
-rw-r--r--src/tool_cfgable.h1
-rw-r--r--src/tool_getparam.c5
-rw-r--r--src/tool_help.c2
-rw-r--r--src/tool_operate.c2
-rw-r--r--tests/data/Makefile.inc3
-rw-r--r--tests/data/test11443
-rw-r--r--tests/data/test11642
-rw-r--r--tests/data/test117250
-rw-r--r--tests/data/test12662
-rw-r--r--tests/data/test12672
-rw-r--r--tests/data/test14001
-rw-r--r--tests/data/test14011
-rw-r--r--tests/data/test14021
-rw-r--r--tests/data/test14031
-rw-r--r--tests/data/test14041
-rw-r--r--tests/data/test14051
-rw-r--r--tests/data/test14061
-rw-r--r--tests/data/test14071
-rw-r--r--tests/data/test14201
-rw-r--r--tests/data/test14293
-rw-r--r--tests/data/test3062
-rw-r--r--tests/data/test663
36 files changed, 396 insertions, 59 deletions
diff --git a/docs/DEPRECATE.md b/docs/DEPRECATE.md
index bb3c05fe1..27bd22ff7 100644
--- a/docs/DEPRECATE.md
+++ b/docs/DEPRECATE.md
@@ -64,3 +64,18 @@ revert if need be.
Remove all global-cache related code from curl around April 2019 (might be
7.66.0).
+
+## HTTP/0.9
+
+Supporting this is non-obvious and might even come as a surprise to some
+users. Potentially even being a security risk in some cases.
+
+### State
+
+curl 7.64.0 introduces options to disable/enable support for this protocol
+version. The default remains supported for now.
+
+### Removal
+
+The support for HTTP/0.9 will be switched to disabled by default in 6 months,
+in the September 2019 release (possibly called curl 7.68.0).
diff --git a/docs/cmdline-opts/Makefile.inc b/docs/cmdline-opts/Makefile.inc
index 76fa5d45f..b99a142ee 100644
--- a/docs/cmdline-opts/Makefile.inc
+++ b/docs/cmdline-opts/Makefile.inc
@@ -1,53 +1,205 @@
# Shared between Makefile.am and CMakeLists.txt
-DPAGES = abstract-unix-socket.d anyauth.d append.d basic.d cacert.d capath.d cert.d \
- cert-status.d cert-type.d ciphers.d compressed.d compressed-ssh.d \
- config.d doh-url.d \
- connect-timeout.d connect-to.d continue-at.d cookie.d cookie-jar.d \
- create-dirs.d crlf.d crlfile.d data-ascii.d data-binary.d data.d \
- data-raw.d data-urlencode.d delegation.d digest.d disable.d \
- disable-eprt.d disable-epsv.d dns-interface.d dns-ipv4-addr.d \
- dns-ipv6-addr.d dns-servers.d dump-header.d egd-file.d engine.d \
- expect100-timeout.d fail.d fail-early.d false-start.d \
- form.d form-string.d ftp-account.d ftp-alternative-to-user.d \
- ftp-create-dirs.d ftp-method.d ftp-pasv.d ftp-port.d ftp-pret.d \
- ftp-skip-pasv-ip.d ftp-ssl-ccc.d ftp-ssl-ccc-mode.d ftp-ssl-control.d \
- get.d globoff.d \
- happy-eyeballs-timeout-ms.d \
- head.d header.d help.d hostpubmd5.d http1.0.d \
- http1.1.d http2.d http2-prior-knowledge.d ignore-content-length.d \
- include.d insecure.d interface.d ipv4.d ipv6.d junk-session-cookies.d \
- keepalive-time.d key.d key-type.d krb.d libcurl.d limit-rate.d \
- list-only.d local-port.d location.d location-trusted.d \
- login-options.d mail-auth.d mail-from.d mail-rcpt.d manual.d \
- max-filesize.d max-redirs.d max-time.d metalink.d negotiate.d netrc.d \
- netrc-file.d netrc-optional.d next.d no-alpn.d no-buffer.d \
- no-keepalive.d no-npn.d noproxy.d no-sessionid.d ntlm.d ntlm-wb.d \
- oauth2-bearer.d output.d pass.d path-as-is.d pinnedpubkey.d post301.d \
- post302.d post303.d preproxy.d progress-bar.d proto.d proto-default.d \
- proto-redir.d proxy1.0.d proxy-anyauth.d proxy-basic.d proxy-cacert.d \
- proxy-capath.d proxy-cert.d proxy-cert-type.d proxy-ciphers.d \
- proxy-crlfile.d proxy.d proxy-digest.d proxy-header.d \
- proxy-insecure.d proxy-key.d proxy-key-type.d proxy-negotiate.d \
- proxy-ntlm.d proxy-pass.d proxy-service-name.d \
- proxy-ssl-allow-beast.d proxy-tlsauthtype.d proxy-tlspassword.d \
- proxy-tlsuser.d proxy-tlsv1.d proxytunnel.d proxy-user.d pubkey.d \
- quote.d random-file.d range.d raw.d referer.d remote-header-name.d \
- remote-name-all.d remote-name.d remote-time.d request.d resolve.d \
- retry-connrefused.d retry.d retry-delay.d retry-max-time.d sasl-ir.d \
- service-name.d show-error.d silent.d socks4a.d socks4.d socks5.d \
- socks5-basic.d socks5-gssapi.d proxy-pinnedpubkey.d \
- socks5-gssapi-nec.d socks5-gssapi-service.d socks5-hostname.d \
- speed-limit.d speed-time.d ssl-allow-beast.d ssl.d ssl-no-revoke.d \
- ssl-reqd.d sslv2.d sslv3.d stderr.d suppress-connect-headers.d \
- tcp-fastopen.d tcp-nodelay.d \
- telnet-option.d tftp-blksize.d tftp-no-options.d time-cond.d \
- tls-max.d \
- tlsauthtype.d tlspassword.d tlsuser.d tlsv1.0.d tlsv1.1.d tlsv1.2.d \
- tlsv1.3.d tlsv1.d trace-ascii.d trace.d trace-time.d tr-encoding.d \
- unix-socket.d upload-file.d url.d use-ascii.d user-agent.d user.d \
- verbose.d version.d write-out.d xattr.d request-target.d \
- styled-output.d tls13-ciphers.d proxy-tls13-ciphers.d \
- disallow-username-in-url.d haproxy-protocol.d
+DPAGES = \
+ abstract-unix-socket.d \
+ anyauth.d \
+ append.d basic.d \
+ cacert.d capath.d \
+ cert-status.d \
+ cert-type.d \
+ cert.d \
+ ciphers.d \
+ compressed-ssh.d \
+ compressed.d \
+ config.d \
+ connect-timeout.d \
+ connect-to.d \
+ continue-at.d \
+ cookie-jar.d \
+ cookie.d \
+ create-dirs.d \
+ crlf.d crlfile.d \
+ data-ascii.d \
+ data-binary.d \
+ data-urlencode.d \
+ data.d data-raw.d \
+ delegation.d \
+ digest.d \
+ disable-eprt.d \
+ disable-epsv.d \
+ disable.d \
+ disallow-username-in-url.d \
+ dns-interface.d \
+ dns-ipv4-addr.d \
+ dns-ipv6-addr.d \
+ dns-servers.d \
+ doh-url.d \
+ dump-header.d \
+ egd-file.d \
+ engine.d \
+ expect100-timeout.d \
+ fail-early.d \
+ fail.d \
+ false-start.d \
+ form-string.d \
+ form.d \
+ ftp-account.d \
+ ftp-alternative-to-user.d \
+ ftp-create-dirs.d \
+ ftp-method.d \
+ ftp-pasv.d \
+ ftp-port.d \
+ ftp-pret.d \
+ ftp-skip-pasv-ip.d \
+ ftp-ssl-ccc-mode.d \
+ ftp-ssl-ccc.d \
+ ftp-ssl-control.d \
+ get.d globoff.d \
+ happy-eyeballs-timeout-ms.d \
+ haproxy-protocol.d \
+ head.d header.d \
+ help.d \
+ hostpubmd5.d \
+ http0.9.d \
+ http1.0.d \
+ http1.1.d http2.d \
+ http2-prior-knowledge.d \
+ ignore-content-length.d \
+ include.d \
+ insecure.d \
+ interface.d \
+ ipv4.d ipv6.d \
+ junk-session-cookies.d \
+ keepalive-time.d \
+ key.d key-type.d \
+ krb.d libcurl.d \
+ limit-rate.d \
+ list-only.d \
+ local-port.d \
+ location-trusted.d \
+ location.d \
+ login-options.d \
+ mail-auth.d \
+ mail-from.d \
+ mail-rcpt.d \
+ manual.d \
+ max-filesize.d \
+ max-redirs.d \
+ max-time.d \
+ metalink.d \
+ negotiate.d \
+ netrc-file.d \
+ netrc-optional.d \
+ netrc.d \
+ next.d no-alpn.d \
+ no-buffer.d \
+ no-keepalive.d \
+ no-npn.d \
+ no-sessionid.d \
+ noproxy.d \
+ ntlm.d ntlm-wb.d \
+ oauth2-bearer.d \
+ output.d pass.d \
+ path-as-is.d \
+ pinnedpubkey.d \
+ post301.d \
+ post302.d \
+ post303.d \
+ preproxy.d \
+ progress-bar.d \
+ proto-default.d \
+ proto-redir.d \
+ proto.d \
+ proxy-anyauth.d \
+ proxy-basic.d \
+ proxy-cacert.d \
+ proxy-capath.d \
+ proxy-cert-type.d \
+ proxy-cert.d \
+ proxy-ciphers.d \
+ proxy-crlfile.d \
+ proxy-digest.d \
+ proxy-header.d \
+ proxy-insecure.d \
+ proxy-key-type.d \
+ proxy-key.d \
+ proxy-negotiate.d \
+ proxy-ntlm.d \
+ proxy-pass.d \
+ proxy-pinnedpubkey.d \
+ proxy-service-name.d \
+ proxy-ssl-allow-beast.d \
+ proxy-tls13-ciphers.d \
+ proxy-tlsauthtype.d \
+ proxy-tlspassword.d \
+ proxy-tlsuser.d \
+ proxy-tlsv1.d \
+ proxy-user.d \
+ proxy.d \
+ proxy1.0.d \
+ proxytunnel.d \
+ pubkey.d quote.d \
+ random-file.d \
+ range.d raw.d \
+ referer.d \
+ remote-header-name.d \
+ remote-name-all.d \
+ remote-name.d \
+ remote-time.d \
+ request-target.d \
+ request.d \
+ resolve.d \
+ retry-connrefused.d \
+ retry-delay.d \
+ retry-max-time.d \
+ retry.d \
+ sasl-ir.d \
+ service-name.d \
+ show-error.d \
+ silent.d \
+ socks4.d socks5.d \
+ socks4a.d \
+ socks5-basic.d \
+ socks5-gssapi-nec.d \
+ socks5-gssapi-service.d \
+ socks5-gssapi.d \
+ socks5-hostname.d \
+ speed-limit.d \
+ speed-time.d \
+ ssl-allow-beast.d \
+ ssl-no-revoke.d \
+ ssl-reqd.d \
+ ssl.d \
+ sslv2.d sslv3.d \
+ stderr.d \
+ styled-output.d \
+ suppress-connect-headers.d \
+ tcp-fastopen.d \
+ tcp-nodelay.d \
+ telnet-option.d \
+ tftp-blksize.d \
+ tftp-no-options.d \
+ time-cond.d \
+ tls-max.d \
+ tls13-ciphers.d \
+ tlsauthtype.d \
+ tlspassword.d \
+ tlsuser.d \
+ tlsv1.0.d \
+ tlsv1.1.d \
+ tlsv1.2.d \
+ tlsv1.3.d tlsv1.d \
+ tr-encoding.d \
+ trace-ascii.d \
+ trace-time.d \
+ trace.d \
+ unix-socket.d \
+ upload-file.d \
+ url.d use-ascii.d \
+ user-agent.d \
+ user.d verbose.d \
+ version.d \
+ write-out.d \
+ xattr.d
OTHERPAGES = page-footer page-header
diff --git a/docs/cmdline-opts/http0.9.d b/docs/cmdline-opts/http0.9.d
new file mode 100644
index 000000000..33fe72d18
--- /dev/null
+++ b/docs/cmdline-opts/http0.9.d
@@ -0,0 +1,14 @@
+Long: http0.9
+Tags: Versions
+Protocols: HTTP
+Added:
+Help: Allow HTTP 0.9 responses
+---
+Tells curl to be fine with HTTP version 0.9 response.
+
+HTTP/0.9 is a completely headerless response and therefore you can also
+connect with this to non-HTTP servers and still get a response since curl will
+simply transparently downgrade - if allowed.
+
+A future curl version will deny continuing if the response isn't at least
+HTTP/1.0 unless this option is used.
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index 1bec4c14d..6d63912d7 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -319,6 +319,8 @@ Do an HTTP GET request. See \fICURLOPT_HTTPGET(3)\fP
Set the request target. \fICURLOPT_REQUEST_TARGET(3)\fP
.IP CURLOPT_HTTP_VERSION
HTTP version to use. \fICURLOPT_HTTP_VERSION(3)\fP
+.IP CURLOPT_HTTP09_ALLOWED
+Allow HTTP/0.9 responses. \fICURLOPT_HTTP09_ALLOWED(3)\fP
.IP CURLOPT_IGNORE_CONTENT_LENGTH
Ignore Content-Length. See \fICURLOPT_IGNORE_CONTENT_LENGTH(3)\fP
.IP CURLOPT_HTTP_CONTENT_DECODING
diff --git a/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3 b/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3
new file mode 100644
index 000000000..3fa44993a
--- /dev/null
+++ b/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3
@@ -0,0 +1,58 @@
+.\" **************************************************************************
+.\" * _ _ ____ _
+.\" * Project ___| | | | _ \| |
+.\" * / __| | | | |_) | |
+.\" * | (__| |_| | _ <| |___
+.\" * \___|\___/|_| \_\_____|
+.\" *
+.\" * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+.\" *
+.\" * This software is licensed as described in the file COPYING, which
+.\" * you should have received as part of this distribution. The terms
+.\" * are also available at https://curl.haxx.se/docs/copyright.html.
+.\" *
+.\" * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+.\" * copies of the Software, and permit persons to whom the Software is
+.\" * furnished to do so, under the terms of the COPYING file.
+.\" *
+.\" * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+.\" * KIND, either express or implied.
+.\" *
+.\" **************************************************************************
+.\"
+.TH CURLOPT_HTTP09_ALLOWED 3 "17 Dec 2018" "libcurl 7.64.0" "curl_easy_setopt options"
+.SH NAME
+CURLOPT_HTTP09 \- allow HTTP/0.9 response
+.SH SYNOPSIS
+#include <curl/curl.h>
+
+CURLcode curl_easy_setopt(CURL *handle, CURLOPT_HTTP09_ALLOWED, long allowed);
+.SH DESCRIPTION
+Pass the long argument \fIallowed\fP set to 1L to allow HTTP/0.9 responses.
+
+A HTTP/0.9 response is a server response entirely without headers and only a
+body, while you can connect to lots of random TCP services and still get a
+response that curl might consider to be HTTP/0.9.
+.SH DEFAULT
+curl allows HTTP/0.9 responses by default.
+
+A future curl version will require this option to be set to allow HTTP/0.9
+responses.
+.SH PROTOCOLS
+HTTP
+.SH EXAMPLE
+.nf
+CURL *curl = curl_easy_init();
+if(curl) {
+ CURLcode ret;
+ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
+ curl_easy_setopt(curl, CURLOPT_HTTP09_ALLOWED, 1L);
+ ret = curl_easy_perform(curl);
+}
+.fi
+.SH AVAILABILITY
+Option added in 7.64.0, present along with HTTP.
+.SH RETURN VALUE
+Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
+.SH "SEE ALSO"
+.BR CURLOPT_SSLVERSION "(3), " CURLOPT_HTTP_VERSION "(3), "
diff --git a/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3 b/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3
index 060db7578..7b7a08144 100644
--- a/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3
+++ b/docs/libcurl/opts/CURLOPT_HTTP_VERSION.3
@@ -84,3 +84,4 @@ Along with HTTP
Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
.BR CURLOPT_SSLVERSION "(3), " CURLOPT_HTTP200ALIASES "(3), "
+.BR CURLOPT_HTTP09_ALLOWED "(3), "
diff --git a/docs/libcurl/opts/Makefile.inc b/docs/libcurl/opts/Makefile.inc
index 9bfd555f1..b21f32356 100644
--- a/docs/libcurl/opts/Makefile.inc
+++ b/docs/libcurl/opts/Makefile.inc
@@ -154,6 +154,7 @@ man_MANS = \
CURLOPT_HEADERDATA.3 \
CURLOPT_HEADERFUNCTION.3 \
CURLOPT_HEADEROPT.3 \
+ CURLOPT_HTTP09_ALLOWED.3 \
CURLOPT_HTTP200ALIASES.3 \
CURLOPT_HTTPAUTH.3 \
CURLOPT_HTTPGET.3 \
@@ -163,9 +164,9 @@ man_MANS = \
CURLOPT_HTTP_CONTENT_DECODING.3 \
CURLOPT_HTTP_TRANSFER_DECODING.3 \
CURLOPT_HTTP_VERSION.3 \
- CURLOPT_TRAILERFUNCTION.3 \
- CURLOPT_TRAILERDATA.3 \
CURLOPT_IGNORE_CONTENT_LENGTH.3 \
+ CURLOPT_TRAILERDATA.3 \
+ CURLOPT_TRAILERFUNCTION.3 \
CURLOPT_INFILESIZE.3 \
CURLOPT_INFILESIZE_LARGE.3 \
CURLOPT_INTERFACE.3 \
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index 8659346ce..f25009c2c 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -421,6 +421,7 @@ CURLOPT_HEADER 7.1
CURLOPT_HEADERDATA 7.10
CURLOPT_HEADERFUNCTION 7.7.2
CURLOPT_HEADEROPT 7.37.0
+CURLOPT_HTTP09_ALLOWED 7.64.0
CURLOPT_HTTP200ALIASES 7.10.3
CURLOPT_HTTPAUTH 7.10.6
CURLOPT_HTTPGET 7.8.1
diff --git a/include/curl/curl.h b/include/curl/curl.h
index bd6183838..88e1f39e8 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -1891,6 +1891,9 @@ typedef enum {
/* pointer to be passed to HTTP_TRAILER_FUNCTION */
CINIT(TRAILERDATA, OBJECTPOINT, 284),
+ /* set this to 1L to allow HTTP/0.9 responses or 0L to disallow */
+ CINIT(HTTP09_ALLOWED, LONG, 285),
+
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
diff --git a/lib/http.c b/lib/http.c
index 07665743c..8866fdf0a 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -3221,6 +3221,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
k->header = FALSE;
k->badheader = HEADER_ALLBAD;
streamclose(conn, "bad HTTP: No end-of-message indicator");
+ if(!data->set.http09_allowed) {
+ failf(data, "Received HTTP/0.9 when not allowed\n");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
break;
}
}
@@ -3254,6 +3258,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(st == STATUS_BAD) {
streamclose(conn, "bad HTTP: No end-of-message indicator");
/* this is not the beginning of a protocol first header line */
+ if(!data->set.http09_allowed) {
+ failf(data, "Received HTTP/0.9 when not allowed\n");
+ return CURLE_UNSUPPORTED_PROTOCOL;
+ }
k->header = FALSE;
if(*nread)
/* since there's more, this is a partial bad header */
diff --git a/lib/setopt.c b/lib/setopt.c
index 27046768c..992bcf915 100644
--- a/lib/setopt.c
+++ b/lib/setopt.c
@@ -860,6 +860,12 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option,
data->set.expect_100_timeout = arg;
break;
+ case CURLOPT_HTTP09_ALLOWED:
+ arg = va_arg(param, unsigned long);
+ if(arg > 1L)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.http09_allowed = arg ? TRUE : FALSE;
+ break;
#endif /* CURL_DISABLE_HTTP */
case CURLOPT_HTTPAUTH:
diff --git a/lib/url.c b/lib/url.c
index 7839dfa7c..5cd286650 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -536,6 +536,7 @@ CURLcode Curl_init_userdefined(struct Curl_easy *data)
set->fnmatch = ZERO_NULL;
set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT;
set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
+ set->http09_allowed = TRUE;
set->httpversion =
#ifdef USE_NGHTTP2
CURL_HTTP_VERSION_2TLS
diff --git a/lib/urldata.h b/lib/urldata.h
index b9658162c..a2655e9e0 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -1743,6 +1743,7 @@ struct UserDefined {
long upkeep_interval_ms; /* Time between calls for connection upkeep. */
bool doh; /* DNS-over-HTTPS enabled */
bool doh_get; /* use GET for DoH requests, instead of POST */
+ bool http09_allowed; /* allow HTTP/0.9 responses */
multidone_func fmultidone;
struct Curl_easy *dohfor; /* this is a DoH request for that transfer */
CURLU *uh; /* URL handle for the current parsed URL */
diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c
index 7d088ae0f..0eb941ef6 100644
--- a/src/tool_cfgable.c
+++ b/src/tool_cfgable.c
@@ -43,6 +43,7 @@ void config_init(struct OperationConfig* config)
config->proto_default = NULL;
config->tcp_nodelay = TRUE; /* enabled by default */
config->happy_eyeballs_timeout_ms = CURL_HET_DEFAULT;
+ config->http09_allowed = TRUE;
}
static void free_config_fields(struct OperationConfig *config)
diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h
index 501c96189..81680dbbb 100644
--- a/src/tool_cfgable.h
+++ b/src/tool_cfgable.h
@@ -146,6 +146,7 @@ struct OperationConfig {
char *krblevel;
char *request_target;
long httpversion;
+ bool http09_allowed;
bool nobuffer;
bool readbusy; /* set when reading input returns EAGAIN */
bool globoff;
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index c0d3a84f2..c7ba5f243 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -199,6 +199,7 @@ static const struct LongShort aliases[]= {
{"01", "http1.1", ARG_NONE},
{"02", "http2", ARG_NONE},
{"03", "http2-prior-knowledge", ARG_NONE},
+ {"09", "http0.9", ARG_BOOL},
{"1", "tlsv1", ARG_NONE},
{"10", "tlsv1.0", ARG_NONE},
{"11", "tlsv1.1", ARG_NONE},
@@ -1183,6 +1184,10 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */
/* HTTP version 2.0 over clean TCP*/
config->httpversion = CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE;
break;
+ case '9':
+ /* Allow HTTP/0.9 responses! */
+ config->http09_allowed = toggle;
+ break;
}
break;
case '1': /* --tlsv1* options */
diff --git a/src/tool_help.c b/src/tool_help.c
index 484c5219c..92cb6ca05 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -176,6 +176,8 @@ static const struct helptxt helptext[] = {
"This help text"},
{" --hostpubmd5 <md5>",
"Acceptable MD5 hash of the host public key"},
+ {" --http0.9",
+ "Allow HTTP 0.9 responses"},
{"-0, --http1.0",
"Use HTTP 1.0"},
{" --http1.1",
diff --git a/src/tool_operate.c b/src/tool_operate.c
index 429e9cf46..7161714d6 100644
--- a/src/tool_operate.c
+++ b/src/tool_operate.c
@@ -1005,6 +1005,8 @@ static CURLcode operate_do(struct GlobalConfig *global,
/* new in libcurl 7.21.6 */
if(config->tr_encoding)
my_setopt(curl, CURLOPT_TRANSFER_ENCODING, 1L);
+ /* new in libcurl 7.64.0 */
+ my_setopt(curl, CURLOPT_HTTP09_ALLOWED, config->http09_allowed);
} /* (built_in_protos & CURLPROTO_HTTP) */
diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc
index 52916c983..9c31d907e 100644
--- a/tests/data/Makefile.inc
+++ b/tests/data/Makefile.inc
@@ -130,7 +130,8 @@ test1144 test1145 test1146 test1147 test1148 test1149 test1150 test1151 \
test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 \
\
test1160 test1161 test1162 test1163 test1164 \
-test1170 test1171 \
+test1170 test1171 test1172 \
+\
test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \
test1216 test1217 test1218 test1219 \
diff --git a/tests/data/test1144 b/tests/data/test1144
index 3fb90936a..84c22dba2 100644
--- a/tests/data/test1144
+++ b/tests/data/test1144
@@ -3,6 +3,7 @@
<keywords>
HTTP
HTTP HEAD
+HTTP/0.9
</keywords>
</info>
@@ -46,7 +47,7 @@ http
HTTP HEAD, receive no headers only body
</name>
<command>
--I http://%HOSTIP:%HTTPPORT/1144
+-I http://%HOSTIP:%HTTPPORT/1144 --http0.9
</command>
</client>
diff --git a/tests/data/test1164 b/tests/data/test1164
index be83aa4f3..a5ce6d11a 100644
--- a/tests/data/test1164
+++ b/tests/data/test1164
@@ -29,7 +29,7 @@ http
HTTP/0.9 GET and all zeroes
</name>
<command option="force-output">
-http://%HOSTIP:%HTTPPORT/1164 -w '%{size_download}\n'
+http://%HOSTIP:%HTTPPORT/1164 -w '%{size_download}\n' --http0.9
</command>
</client>
diff --git a/tests/data/test1172 b/tests/data/test1172
new file mode 100644
index 000000000..6e61720bd
--- /dev/null
+++ b/tests/data/test1172
@@ -0,0 +1,50 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP/0.9
+</keywords>
+</info>
+
+#
+# Server-side
+<reply>
+<data>
+-foo- swsclose
+</data>
+<datacheck>
+</datacheck>
+</reply>
+
+#
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP/0.9 GET response denied
+ </name>
+ <command>
+http://%HOSTIP:%HTTPPORT/1172 --no-http0.9
+</command>
+</client>
+
+#
+# Verify data after the test has been "shot"
+<verify>
+<strip>
+^User-Agent:.*
+</strip>
+<protocol>
+GET /1172 HTTP/1.1
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol>
+# unsupported protocol
+<errorcode>
+1
+</errorcode>
+</verify>
+</testcase>
diff --git a/tests/data/test1266 b/tests/data/test1266
index 75ed7bdc9..cab11efa0 100644
--- a/tests/data/test1266
+++ b/tests/data/test1266
@@ -26,7 +26,7 @@ http
HTTP GET with a single-byte HTTP/0.9 response
</name>
<command>
-http://%HOSTIP:%HTTPPORT/1266
+http://%HOSTIP:%HTTPPORT/1266 --http0.9
</command>
</client>
diff --git a/tests/data/test1267 b/tests/data/test1267
index 8f2a63b78..82d37445d 100644
--- a/tests/data/test1267
+++ b/tests/data/test1267
@@ -26,7 +26,7 @@ http
HTTP GET with a invalid HTTP/1 response line start
</name>
<command>
-http://%HOSTIP:%HTTPPORT/1267
+http://%HOSTIP:%HTTPPORT/1267 --http0.9
</command>
</client>
diff --git a/tests/data/test1400 b/tests/data/test1400
index 10faef39b..36ddd0e91 100644
--- a/tests/data/test1400
+++ b/tests/data/test1400
@@ -54,6 +54,7 @@ s/(USERAGENT, \")[^\"]+/${1}stripped/
$_ = '' if /CURLOPT_SSL_VERIFYPEER/
$_ = '' if /CURLOPT_SSH_KNOWNHOSTS/
$_ = '' if /CURLOPT_HTTP_VERSION/
+$_ = '' if /CURLOPT_HTTP09_ALLOWED/
</stripfile>
<file name="log/test1400.c" mode="text">
/********* Sample code generated by the curl command line tool **********
diff --git a/tests/data/test1401 b/tests/data/test1401
index f330931c9..d7033e0b5 100644
--- a/tests/data/test1401
+++ b/tests/data/test1401
@@ -87,6 +87,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, slist1);
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "MyUA");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
+ curl_easy_setopt(hnd, CURLOPT_HTTP09_ALLOWED, 1L);
curl_easy_setopt(hnd, CURLOPT_COOKIE, "chocolate=chip");
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
diff --git a/tests/data/test1402 b/tests/data/test1402
index 9a9428376..978b26162 100644
--- a/tests/data/test1402
+++ b/tests/data/test1402
@@ -79,6 +79,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)16);
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
+ curl_easy_setopt(hnd, CURLOPT_HTTP09_ALLOWED, 1L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
diff --git a/tests/data/test1403 b/tests/data/test1403
index 79cdf4964..9c838d0ed 100644
--- a/tests/data/test1403
+++ b/tests/data/test1403
@@ -74,6 +74,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_URL, "http://%HOSTIP:%HTTPPORT/we/want/1403?foo=bar&baz=quux");
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
+ curl_easy_setopt(hnd, CURLOPT_HTTP09_ALLOWED, 1L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
diff --git a/tests/data/test1404 b/tests/data/test1404
index 9c6f2e726..a00bf10a3 100644
--- a/tests/data/test1404
+++ b/tests/data/test1404
@@ -143,6 +143,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_MIMEPOST, mime1);
curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
+ curl_easy_setopt(hnd, CURLOPT_HTTP09_ALLOWED, 1L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
diff --git a/tests/data/test1405 b/tests/data/test1405
index 73769eed1..4f477c7d9 100644
--- a/tests/data/test1405
+++ b/tests/data/test1405
@@ -136,6 +136,7 @@ $_ = '' if /CURLOPT_MAXREDIRS/
$_ = '' if /CURLOPT_SSL_VERIFYPEER/
$_ = '' if /CURLOPT_SSH_KNOWNHOSTS/
$_ = '' if /CURLOPT_HTTP_VERSION/
+$_ = '' if /CURLOPT_HTTP09_ALLOWED/
</stripfile>
</verify>
</testcase>
diff --git a/tests/data/test1406 b/tests/data/test1406
index 796dd2254..7d973e7ef 100644
--- a/tests/data/test1406
+++ b/tests/data/test1406
@@ -122,6 +122,7 @@ $_ = '' if /CURLOPT_MAXREDIRS/
$_ = '' if /CURLOPT_SSL_VERIFYPEER/
$_ = '' if /CURLOPT_SSH_KNOWNHOSTS/
$_ = '' if /CURLOPT_HTTP_VERSION/
+$_ = '' if /CURLOPT_HTTP09_ALLOWED/
</stripfile>
</verify>
</testcase>
diff --git a/tests/data/test1407 b/tests/data/test1407
index 9800eeef3..883cf4064 100644
--- a/tests/data/test1407
+++ b/tests/data/test1407
@@ -100,6 +100,7 @@ $_ = '' if /CURLOPT_MAXREDIRS/
$_ = '' if /CURLOPT_SSL_VERIFYPEER/
$_ = '' if /CURLOPT_SSH_KNOWNHOSTS/
$_ = '' if /CURLOPT_HTTP_VERSION/
+$_ = '' if /CURLOPT_HTTP09_ALLOWED/
</stripfile>
</verify>
</testcase>
diff --git a/tests/data/test1420 b/tests/data/test1420
index 081ac6bbb..c3d31f349 100644
--- a/tests/data/test1420
+++ b/tests/data/test1420
@@ -66,6 +66,7 @@ int main(int argc, char *argv[])
curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
curl_easy_setopt(hnd, CURLOPT_URL, "imap://%HOSTIP:%IMAPPORT/1420/;MAILINDEX=1");
curl_easy_setopt(hnd, CURLOPT_USERPWD, "user:secret");
+ curl_easy_setopt(hnd, CURLOPT_HTTP09_ALLOWED, 1L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
diff --git a/tests/data/test1429 b/tests/data/test1429
index 114dc0dba..20b031a1e 100644
--- a/tests/data/test1429
+++ b/tests/data/test1429
@@ -3,6 +3,7 @@
<keywords>
HTTP
HTTP GET
+HTTP/0.9
</keywords>
</info>
@@ -34,7 +35,7 @@ http
HTTP GET with 4-digit response code
</name>
<command>
-http://%HOSTIP:%HTTPPORT/1429 --write-out '%{response_code}'
+http://%HOSTIP:%HTTPPORT/1429 --write-out '%{response_code}' --http0.9
</command>
</client>
diff --git a/tests/data/test306 b/tests/data/test306
index 95d4cef35..17306f949 100644
--- a/tests/data/test306
+++ b/tests/data/test306
@@ -45,7 +45,7 @@ https
HTTPS GET, receive no headers only data!
</name>
<command>
--k https://%HOSTIP:%HTTPSPORT/306
+-k https://%HOSTIP:%HTTPSPORT/306 --http0.9
</command>
</client>
diff --git a/tests/data/test66 b/tests/data/test66
index a018d8fd4..7b9af2953 100644
--- a/tests/data/test66
+++ b/tests/data/test66
@@ -3,6 +3,7 @@
<keywords>
HTTP
HTTP GET
+HTTP/0.9
</keywords>
</info>
# Server-side
@@ -21,7 +22,7 @@ http
HTTP GET without headers in the response
</name>
<command>
-http://%HOSTIP:%HTTPPORT/66
+http://%HOSTIP:%HTTPPORT/66 --http0.9
</command>
</client>