lib: sanitize conditional exclusion around MIME

The introduction of CURL_DISABLE_MIME came with some additional bugs:
- Disabled MIME is compiled-in anyway if SMTP and/or IMAP is enabled.
- CURLOPT_MIMEPOST, CURLOPT_MIME_OPTIONS and CURLOPT_HTTPHEADER are
  conditioned on HTTP, although also needed for SMTP and IMAP MIME mail
  uploads.

In addition, the CURLOPT_HTTPHEADER and --header documentation does not
mention their use for MIME mail.

This commit fixes the problems above.

Closes #9610
This commit is contained in:
Patrick Monnerat 2022-09-28 18:12:15 +02:00 committed by Daniel Stenberg
parent 75670e4573
commit 2437fac013
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
7 changed files with 101 additions and 55 deletions

View File

@ -4,7 +4,7 @@ Long: header
Short: H
Arg: <header/@file>
Help: Pass custom header(s) to server
Protocols: HTTP
Protocols: HTTP IMAP SMTP
Category: http
See-also: user-agent referer
Example: -H "X-First-Name: Joe" $URL
@ -12,16 +12,22 @@ Example: -H "User-Agent: yes-please/2000" $URL
Example: -H "Host:" $URL
Added: 5.0
---
Extra header to include in the request when sending HTTP to a server. You may
specify any number of extra headers. Note that if you should add a custom
header that has the same name as one of the internal ones curl would use, your
externally set header will be used instead of the internal one. This allows
you to make even trickier stuff than curl would normally do. You should not
replace internally set headers without knowing perfectly well what you are
doing. Remove an internal header by giving a replacement without content on
the right side of the colon, as in: -H "Host:". If you send the custom
header with no-value then its header must be terminated with a semicolon, such
as \-H "X-Custom-Header;" to send "X-Custom-Header:".
Extra header to include in information sent. When used within an HTTP request,
it is added to the regular request headers.
For an IMAP or SMTP MIME uploaded mail built with --form options, it is
prepended to the resulting MIME document, effectively incuding it at the mail
global level. It does not affect raw uploaded mails (Added in 7.56.0).
You may specify any number of extra headers. Note that if you should add a
custom header that has the same name as one of the internal ones curl would
use, your externally set header will be used instead of the internal one.
This allows you to make even trickier stuff than curl would normally do. You
should not replace internally set headers without knowing perfectly well what
you are doing. Remove an internal header by giving a replacement without
content on the right side of the colon, as in: -H "Host:". If you send the
custom header with no-value then its header must be terminated with a
semicolon, such as \-H "X-Custom-Header;" to send "X-Custom-Header:".
curl will make sure that each header you add/replace is sent with the proper
end-of-line marker, you should thus **not** add that as a part of the header
@ -32,15 +38,20 @@ This option can take an argument in @filename style, which then adds a header
for each line in the input file. Using @- will make curl read the header file
from stdin. Added in 7.55.0.
Please note that most anti-spam utilities check the presence and value of
several MIME mail headers: these are "From:", "To:", "Date:" and "Subject:"
among others and should be added with this option.
You need --proxy-header to send custom headers intended for an HTTP
proxy. Added in 7.37.0.
Passing on a "Transfer-Encoding: chunked" header when doing an HTTP request
with a request body, will make curl send the data using chunked encoding.
**WARNING**: headers set with this option will be set in all requests - even
after redirects are followed, like when told with --location. This can lead to
the header being sent to other hosts than the original host, so sensitive
headers should be used with caution combined with following redirects.
**WARNING**: headers set with this option will be set in all HTTP requests
- even after redirects are followed, like when told with --location. This can
lead to the header being sent to other hosts than the original host, so
sensitive headers should be used with caution combined with following
redirects.
This option can be used multiple times to add/replace/remove multiple headers.

View File

@ -37,6 +37,11 @@ Pass a pointer to a linked list of HTTP headers to pass to the server and/or
proxy in your HTTP request. The same list can be used for both host and proxy
requests!
When used within an IMAP or SMTP request to upload a MIME mail, the given
header list establishes the document-level MIME headers to prepend to the
uploaded document described by \fICURLOPT_MIMEPOST(3)\fP. This does not affect
raw mail uploads.
The linked list should be a fully valid list of \fBstruct curl_slist\fP
structs properly filled in. Use \fIcurl_slist_append(3)\fP to create the list
and \fIcurl_slist_free_all(3)\fP to clean up an entire list. If you add a
@ -52,8 +57,8 @@ because libcurl adds CRLF after each header item. Failure to comply with this
will result in strange bugs because the server will most likely ignore part of
the headers you specified.
The first line in a request (containing the method, usually a GET or POST) is
not a header and cannot be replaced using this option. Only the lines
The first line in an HTTP request (containing the method, usually a GET or
POST) is not a header and cannot be replaced using this option. Only the lines
following the request-line are headers. Adding this method line in this list
of headers will only cause your request to send an invalid header. Use
\fICURLOPT_CUSTOMREQUEST(3)\fP to change the method.
@ -65,14 +70,14 @@ the list.
Pass a NULL to this option to reset back to no custom headers.
The most commonly replaced headers have "shortcuts" in the options
The most commonly replaced HTTP headers have "shortcuts" in the options
\fICURLOPT_COOKIE(3)\fP, \fICURLOPT_USERAGENT(3)\fP and
\fICURLOPT_REFERER(3)\fP. We recommend using those.
There's an alternative option that sets or replaces headers only for requests
that are sent with CONNECT to a proxy: \fICURLOPT_PROXYHEADER(3)\fP. Use
\fICURLOPT_HEADEROPT(3)\fP to control the behavior.
.SH SPECIFIC HEADERS
.SH SPECIFIC HTTP HEADERS
Setting some specific headers will cause libcurl to act differently.
.IP "Host:"
The specified host name will be used for cookie matching if the cookie engine
@ -82,6 +87,24 @@ field and Host: will not be sent at all over the wire.
.IP "Transfer-Encoding: chunked"
Tells libcurl the upload is to be done using this chunked encoding instead of
providing the Content-Length: field in the request.
.SH SPECIFIC MIME HEADERS
When used to build a MIME e-mail for IMAP or SMTP, the following
document-level headers can be set to override libcurl-generated values:
.IP "Mime-Version:"
Tells the parser at the receiving site how to interpret the MIME framing.
It defaults to "1.0" and should normally not be altered.
.IP "Content-Type:"
Indicates the document's global structure type. By default, libcurl sets it
to "multipart/mixed", describing a document made of independent parts. When a
MIME mail is only composed of alternative representations of the same data
(i.e.: HTML and plain text), this header must be set to "multipart/alternative".
In all cases the value must be of the form "multipart/*" to respect the
document structure and may not include the "boundary=" parameter.
.P
Other specific headers that do not have a libcurl default value but are
strongly desired by mail delivery and user agents should also be included.
These are "From:", "To:", "Date:" and "Subject:" among others and their
presence and value is generally checked by anti-spam utilities.
.SH SECURITY CONCERNS
By default, this option makes libcurl send the given headers in all HTTP
requests done by this handle. You should therefore use this option with
@ -108,7 +131,7 @@ permitted with the \fICURLOPT_UNRESTRICTED_AUTH(3)\fP option.
.SH DEFAULT
NULL
.SH PROTOCOLS
HTTP
HTTP, IMAP and SMTP
.SH EXAMPLE
.nf
CURL *curl = curl_easy_init();
@ -130,9 +153,10 @@ if(curl) {
.fi
.SH AVAILABILITY
As long as HTTP is enabled
As long as HTTP is enabled. Use in MIME mail added in 7.56.0.
.SH RETURN VALUE
Returns CURLE_OK if HTTP is supported, and CURLE_UNKNOWN_OPTION if not.
.SH "SEE ALSO"
.BR CURLOPT_CUSTOMREQUEST "(3), " CURLOPT_HEADEROPT "(3), "
.BR CURLOPT_PROXYHEADER "(3), " CURLOPT_HEADER "(3)"
.BR CURLOPT_PROXYHEADER "(3), " CURLOPT_HEADER "(3), "
.BR CURLOPT_MIMEPOST "(3), " curl_mime_init "(3)"

View File

@ -31,8 +31,9 @@
#include "urldata.h"
#include "sendf.h"
#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
!defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
!defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_IMAP))
#if defined(HAVE_LIBGEN_H) && defined(HAVE_BASENAME)
#include <libgen.h>
@ -1924,8 +1925,8 @@ void Curl_mime_unpause(curl_mimepart *part)
}
#else /* !CURL_DISABLE_HTTP && !CURL_DISABLE_MIME ||
!CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP */
#else /* !CURL_DISABLE_MIME && (!CURL_DISABLE_HTTP ||
!CURL_DISABLE_SMTP || !CURL_DISABLE_IMAP) */
/* Mime not compiled in: define stubs for externally-referenced functions. */
curl_mime *curl_mime_init(CURL *easy)

View File

@ -134,8 +134,9 @@ struct curl_mimepart {
CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...);
#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
!defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
!defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_IMAP))
/* Prototypes. */
void Curl_mime_initpart(struct curl_mimepart *part, struct Curl_easy *easy);

View File

@ -654,6 +654,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.upload = FALSE;
break;
#ifndef CURL_DISABLE_MIME
case CURLOPT_HTTPPOST:
/*
* Set to make us do HTTP POST
@ -662,6 +663,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.method = HTTPREQ_POST_FORM;
data->set.opt_no_body = FALSE; /* this is implied */
break;
#endif
case CURLOPT_AWS_SIGV4:
/*
@ -677,18 +679,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
data->set.httpauth = CURLAUTH_AWS_SIGV4;
break;
case CURLOPT_MIMEPOST:
/*
* Set to make us do MIME/form POST
*/
result = Curl_mime_set_subparts(&data->set.mimepost,
va_arg(param, curl_mime *), FALSE);
if(!result) {
data->set.method = HTTPREQ_POST_MIME;
data->set.opt_no_body = FALSE; /* this is implied */
}
break;
case CURLOPT_REFERER:
/*
* String to set in the HTTP Referer: field.
@ -710,13 +700,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
va_arg(param, char *));
break;
case CURLOPT_HTTPHEADER:
/*
* Set a list with HTTP headers to use (or replace internals with)
*/
data->set.headers = va_arg(param, struct curl_slist *);
break;
#ifndef CURL_DISABLE_PROXY
case CURLOPT_PROXYHEADER:
/*
@ -954,6 +937,36 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif /* CURL_DISABLE_HTTP */
#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \
!defined(CURL_DISABLE_IMAP)
# if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MIME)
case CURLOPT_HTTPHEADER:
/*
* Set a list with HTTP headers to use (or replace internals with)
*/
data->set.headers = va_arg(param, struct curl_slist *);
break;
# endif
# ifndef CURL_DISABLE_MIME
case CURLOPT_MIMEPOST:
/*
* Set to make us do MIME POST
*/
result = Curl_mime_set_subparts(&data->set.mimepost,
va_arg(param, curl_mime *), FALSE);
if(!result) {
data->set.method = HTTPREQ_POST_MIME;
data->set.opt_no_body = FALSE; /* this is implied */
}
break;
case CURLOPT_MIME_OPTIONS:
data->set.mime_options = (unsigned int)va_arg(param, long);
break;
# endif
#endif
case CURLOPT_HTTPAUTH:
/*
* Set HTTP Authentication type BITMASK.
@ -2659,13 +2672,6 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
break;
#endif
#if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_MIME)) || \
!defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP)
case CURLOPT_MIME_OPTIONS:
data->set.mime_options = (unsigned int)va_arg(param, long);
break;
#endif
case CURLOPT_SASL_AUTHZID:
/* Authorization identity (identity to act as) */
result = Curl_setstropt(&data->set.str[STRING_SASL_AUTHZID],

View File

@ -251,7 +251,7 @@ const struct helptxt helptext[] = {
CURLHELP_HTTP | CURLHELP_FTP | CURLHELP_FILE},
{"-H, --header <header/@file>",
"Pass custom header(s) to server",
CURLHELP_HTTP},
CURLHELP_HTTP | CURLHELP_IMAP | CURLHELP_SMTP},
{"-h, --help <category>",
"Get help for commands",
CURLHELP_IMPORTANT | CURLHELP_CURL},

View File

@ -28,6 +28,9 @@ body
#
# Client-side
<client>
<features>
Mime
</features>
<server>
imap
</server>