mirror of
https://github.com/curl/curl.git
synced 2026-07-20 10:07:17 +03:00
parent
02214d98f7
commit
c3f9ef13f6
5 changed files with 165 additions and 1 deletions
10
lib/mime.c
10
lib/mime.c
|
|
@ -1708,6 +1708,16 @@ static CURLcode add_content_disposition(struct Curl_easy *data,
|
|||
CURLcode result = CURLE_OK;
|
||||
char *name = NULL;
|
||||
char *filename = NULL;
|
||||
/* The mail (and legacy mime_formescape) strategy quotes the name and
|
||||
filename with a backslash and has no in-band way to represent a CR or
|
||||
LF, so one embedded in the value would split the generated header. The
|
||||
form strategy percent-encodes CR/LF (see escape_string) and is safe. */
|
||||
bool backslash = (strategy == MIMESTRATEGY_MAIL) ||
|
||||
(data && data->set.mime_formescape);
|
||||
if(backslash &&
|
||||
((part->name && part->name[strcspn(part->name, "\r\n")]) ||
|
||||
(part->filename && part->filename[strcspn(part->filename, "\r\n")])))
|
||||
return CURLE_BAD_FUNCTION_ARGUMENT;
|
||||
|
||||
if(part->name) {
|
||||
name = escape_string(data, part->name, strategy);
|
||||
|
|
|
|||
|
|
@ -284,7 +284,7 @@ test3100 test3101 test3102 test3103 test3104 test3105 test3106 \
|
|||
test3200 test3201 test3202 test3203 test3204 test3205 test3206 test3207 \
|
||||
test3208 test3209 test3210 test3211 test3212 test3213 test3214 test3215 \
|
||||
test3216 test3217 test3218 test3219 test3220 test3221 test3222 \
|
||||
test3223 test3224 test3225 test3226 \
|
||||
test3223 test3224 test3225 test3226 test3227 \
|
||||
\
|
||||
test3300 test3301 test3302 test3303 test3304 test3305 \
|
||||
\
|
||||
|
|
|
|||
20
tests/data/test3227
Normal file
20
tests/data/test3227
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="US-ASCII"?>
|
||||
<testcase>
|
||||
<info>
|
||||
<keywords>
|
||||
unittest
|
||||
mime
|
||||
SMTP
|
||||
</keywords>
|
||||
</info>
|
||||
|
||||
# Client-side
|
||||
<client>
|
||||
<features>
|
||||
unittest
|
||||
</features>
|
||||
<name>
|
||||
reject CR and LF in mail mime part name and filename
|
||||
</name>
|
||||
</client>
|
||||
</testcase>
|
||||
|
|
@ -48,4 +48,5 @@ TESTS_C = \
|
|||
unit2600.c unit2601.c unit2602.c unit2603.c unit2604.c unit2605.c \
|
||||
unit3200.c unit3205.c \
|
||||
unit3211.c unit3212.c unit3213.c unit3214.c unit3216.c unit3219.c \
|
||||
unit3227.c \
|
||||
unit3300.c unit3301.c unit3302.c unit3303.c unit3304.c unit3400.c
|
||||
|
|
|
|||
133
tests/unit/unit3227.c
Normal file
133
tests/unit/unit3227.c
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/***************************************************************************
|
||||
* _ _ ____ _
|
||||
* Project ___| | | | _ \| |
|
||||
* / __| | | | |_) | |
|
||||
* | (__| |_| | _ <| |___
|
||||
* \___|\___/|_| \_\_____|
|
||||
*
|
||||
* Copyright (C) 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.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.
|
||||
*
|
||||
* SPDX-License-Identifier: curl
|
||||
*
|
||||
***************************************************************************/
|
||||
#include "unitcheck.h"
|
||||
#include "urldata.h"
|
||||
#include "mime.h"
|
||||
|
||||
#if !defined(CURL_DISABLE_MIME) && (!defined(CURL_DISABLE_HTTP) || \
|
||||
!defined(CURL_DISABLE_SMTP) || !defined(CURL_DISABLE_IMAP))
|
||||
|
||||
/* does any generated part header carry a raw CR or LF, i.e. a split line? */
|
||||
static bool headers_have_ctrl(const curl_mimepart *part)
|
||||
{
|
||||
const struct curl_slist *h;
|
||||
for(h = part->curlheaders; h; h = h->next)
|
||||
if(h->data[strcspn(h->data, "\r\n")])
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static CURLcode t3227_setup(void)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
global_init(CURL_GLOBAL_ALL);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void t3227_stop(CURL *easy, curl_mime *mime)
|
||||
{
|
||||
curl_mime_free(mime);
|
||||
if(easy)
|
||||
curl_easy_cleanup(easy);
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
static CURLcode test_unit3227(const char *arg)
|
||||
{
|
||||
CURL *easy = NULL;
|
||||
curl_mime *mime = NULL;
|
||||
curl_mimepart *part;
|
||||
|
||||
UNITTEST_BEGIN(t3227_setup())
|
||||
|
||||
easy = curl_easy_init();
|
||||
abort_unless(easy, "curl_easy_init()");
|
||||
mime = curl_mime_init(easy);
|
||||
abort_unless(mime, "curl_mime_init()");
|
||||
|
||||
/* A CR or LF in the mail-part name or filename would split the generated
|
||||
Content-Disposition header. The mail strategy must reject it. */
|
||||
|
||||
part = curl_mime_addpart(mime);
|
||||
abort_unless(part, "curl_mime_addpart()");
|
||||
curl_mime_data(part, "x", 1);
|
||||
curl_mime_filename(part, "a\r\nX-Injected: 1");
|
||||
fail_unless(Curl_mime_prepare_headers(easy, part, NULL, NULL,
|
||||
MIMESTRATEGY_MAIL) ==
|
||||
CURLE_BAD_FUNCTION_ARGUMENT,
|
||||
"CRLF filename accepted for mail");
|
||||
|
||||
part = curl_mime_addpart(mime);
|
||||
abort_unless(part, "curl_mime_addpart()");
|
||||
curl_mime_data(part, "x", 1);
|
||||
curl_mime_name(part, "a\nb");
|
||||
fail_unless(Curl_mime_prepare_headers(easy, part, NULL, NULL,
|
||||
MIMESTRATEGY_MAIL) ==
|
||||
CURLE_BAD_FUNCTION_ARGUMENT,
|
||||
"LF name accepted for mail");
|
||||
|
||||
part = curl_mime_addpart(mime);
|
||||
abort_unless(part, "curl_mime_addpart()");
|
||||
curl_mime_data(part, "x", 1);
|
||||
curl_mime_filename(part, "a\rb");
|
||||
fail_unless(Curl_mime_prepare_headers(easy, part, NULL, NULL,
|
||||
MIMESTRATEGY_MAIL) ==
|
||||
CURLE_BAD_FUNCTION_ARGUMENT,
|
||||
"CR filename accepted for mail");
|
||||
|
||||
/* A regular name and filename are accepted and produce a clean header. */
|
||||
part = curl_mime_addpart(mime);
|
||||
abort_unless(part, "curl_mime_addpart()");
|
||||
curl_mime_data(part, "x", 1);
|
||||
curl_mime_name(part, "field");
|
||||
curl_mime_filename(part, "readme.txt");
|
||||
fail_unless(Curl_mime_prepare_headers(easy, part, NULL, NULL,
|
||||
MIMESTRATEGY_MAIL) == CURLE_OK,
|
||||
"plain mail part rejected");
|
||||
fail_if(headers_have_ctrl(part), "clean mail header split");
|
||||
|
||||
/* The HTTP form strategy percent-encodes CR/LF, so it stays accepted and
|
||||
produces no split line. */
|
||||
part = curl_mime_addpart(mime);
|
||||
abort_unless(part, "curl_mime_addpart()");
|
||||
curl_mime_data(part, "x", 1);
|
||||
curl_mime_filename(part, "a\r\nX-Injected: 1");
|
||||
fail_unless(Curl_mime_prepare_headers(easy, part, NULL, NULL,
|
||||
MIMESTRATEGY_FORM) == CURLE_OK,
|
||||
"CRLF filename rejected for form");
|
||||
fail_if(headers_have_ctrl(part), "form header split despite encoding");
|
||||
|
||||
UNITTEST_END(t3227_stop(easy, mime))
|
||||
}
|
||||
|
||||
#else /* mime disabled */
|
||||
|
||||
static CURLcode test_unit3227(const char *arg)
|
||||
{
|
||||
UNITTEST_BEGIN_SIMPLE
|
||||
puts("nothing to do when mime is disabled");
|
||||
UNITTEST_END_SIMPLE
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue