From 006ff62d8c51f664c167c6337f009f9f65dd8ea7 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 17 Dec 2018 15:46:56 +0100 Subject: [PATCH] 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 --- docs/DEPRECATE.md | 15 ++ docs/cmdline-opts/Makefile.inc | 250 +++++++++++++++++---- docs/cmdline-opts/http0.9.d | 14 ++ docs/libcurl/curl_easy_setopt.3 | 2 + docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3 | 58 +++++ docs/libcurl/opts/CURLOPT_HTTP_VERSION.3 | 1 + docs/libcurl/opts/Makefile.inc | 5 +- docs/libcurl/symbols-in-versions | 1 + include/curl/curl.h | 3 + lib/http.c | 8 + lib/setopt.c | 6 + lib/url.c | 1 + lib/urldata.h | 1 + src/tool_cfgable.c | 1 + src/tool_cfgable.h | 1 + src/tool_getparam.c | 5 + src/tool_help.c | 2 + src/tool_operate.c | 2 + tests/data/Makefile.inc | 3 +- tests/data/test1144 | 3 +- tests/data/test1164 | 2 +- tests/data/test1172 | 50 +++++ tests/data/test1266 | 2 +- tests/data/test1267 | 2 +- tests/data/test1400 | 1 + tests/data/test1401 | 1 + tests/data/test1402 | 1 + tests/data/test1403 | 1 + tests/data/test1404 | 1 + tests/data/test1405 | 1 + tests/data/test1406 | 1 + tests/data/test1407 | 1 + tests/data/test1420 | 1 + tests/data/test1429 | 3 +- tests/data/test306 | 2 +- tests/data/test66 | 3 +- 36 files changed, 396 insertions(+), 59 deletions(-) create mode 100644 docs/cmdline-opts/http0.9.d create mode 100644 docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.3 create mode 100644 tests/data/test1172 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, , 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 + +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 ", "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 @@ HTTP HTTP HEAD +HTTP/0.9 @@ -46,7 +47,7 @@ http HTTP HEAD, receive no headers only body --I http://%HOSTIP:%HTTPPORT/1144 +-I http://%HOSTIP:%HTTPPORT/1144 --http0.9 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 -http://%HOSTIP:%HTTPPORT/1164 -w '%{size_download}\n' +http://%HOSTIP:%HTTPPORT/1164 -w '%{size_download}\n' --http0.9 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 @@ + + + +HTTP +HTTP/0.9 + + + +# +# Server-side + + +-foo- swsclose + + + + + +# +# Client-side + + +http + + +HTTP/0.9 GET response denied + + +http://%HOSTIP:%HTTPPORT/1172 --no-http0.9 + + + +# +# Verify data after the test has been "shot" + + +^User-Agent:.* + + +GET /1172 HTTP/1.1 +Host: %HOSTIP:%HTTPPORT +Accept: */* + + +# unsupported protocol + +1 + + + 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 -http://%HOSTIP:%HTTPPORT/1266 +http://%HOSTIP:%HTTPPORT/1266 --http0.9 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 -http://%HOSTIP:%HTTPPORT/1267 +http://%HOSTIP:%HTTPPORT/1267 --http0.9 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/ /********* 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/ 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/ 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/ 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 @@ HTTP HTTP GET +HTTP/0.9 @@ -34,7 +35,7 @@ http HTTP GET with 4-digit response code -http://%HOSTIP:%HTTPPORT/1429 --write-out '%{response_code}' +http://%HOSTIP:%HTTPPORT/1429 --write-out '%{response_code}' --http0.9 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! --k https://%HOSTIP:%HTTPSPORT/306 +-k https://%HOSTIP:%HTTPSPORT/306 --http0.9 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 @@ HTTP HTTP GET +HTTP/0.9 # Server-side @@ -21,7 +22,7 @@ http HTTP GET without headers in the response -http://%HOSTIP:%HTTPPORT/66 +http://%HOSTIP:%HTTPPORT/66 --http0.9