diff --git a/0004-curl-7.59.0-http2-GOAWAY.patch b/0004-curl-7.59.0-http2-GOAWAY.patch new file mode 100644 index 0000000..790c27b --- /dev/null +++ b/0004-curl-7.59.0-http2-GOAWAY.patch @@ -0,0 +1,344 @@ +From 01f15fd3d66655872e10c36dd6a631f491fbbed0 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 10 Mar 2018 23:48:43 +0100 +Subject: [PATCH 1/2] http2: mark the connection for close on GOAWAY +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +... don't consider it an error! + +Assisted-by: Jay Satiro +Reported-by: Ɓukasz Domeradzki +Fixes #2365 +Closes #2375 + +Upstream-commit: 8b498a875c975294545581282289991bbcfeabf4 +Signed-off-by: Kamil Dudka +--- + lib/http.h | 5 ++--- + lib/http2.c | 33 +++++++++++++++++++++------------ + lib/multi.c | 9 +++------ + 3 files changed, 26 insertions(+), 21 deletions(-) + +diff --git a/lib/http.h b/lib/http.h +index a845f56..e8e41e3 100644 +--- a/lib/http.h ++++ b/lib/http.h +@@ -7,7 +7,7 @@ + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * +- * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. ++ * 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 +@@ -174,8 +174,6 @@ struct HTTP { + size_t pauselen; /* the number of bytes left in data */ + bool closed; /* TRUE on HTTP2 stream close */ + bool close_handled; /* TRUE if stream closure is handled by libcurl */ +- uint32_t error_code; /* HTTP/2 error code */ +- + char *mem; /* points to a buffer in memory to store received data */ + size_t len; /* size of the buffer 'mem' points to */ + size_t memlen; /* size of data copied to mem */ +@@ -228,6 +226,7 @@ struct http_conn { + /* list of settings that will be sent */ + nghttp2_settings_entry local_settings[3]; + size_t local_settings_num; ++ uint32_t error_code; /* HTTP/2 error code */ + #else + int unused; /* prevent a compiler warning */ + #endif +diff --git a/lib/http2.c b/lib/http2.c +index 0e55801..14ab0f7 100644 +--- a/lib/http2.c ++++ b/lib/http2.c +@@ -205,7 +205,6 @@ void Curl_http2_setup_req(struct Curl_easy *data) + http->status_code = -1; + http->pausedata = NULL; + http->pauselen = 0; +- http->error_code = NGHTTP2_NO_ERROR; + http->closed = FALSE; + http->close_handled = FALSE; + http->mem = data->state.buffer; +@@ -218,6 +217,7 @@ void Curl_http2_setup_conn(struct connectdata *conn) + { + conn->proto.httpc.settings.max_concurrent_streams = + DEFAULT_MAX_CONCURRENT_STREAMS; ++ conn->proto.httpc.error_code = NGHTTP2_NO_ERROR; + } + + /* +@@ -778,6 +778,7 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, + (void)stream_id; + + if(stream_id) { ++ struct http_conn *httpc; + /* get the stream from the hash based on Stream ID, stream ID zero is for + connection-oriented stuff */ + data_s = nghttp2_session_get_stream_user_data(session, stream_id); +@@ -792,10 +793,11 @@ static int on_stream_close(nghttp2_session *session, int32_t stream_id, + if(!stream) + return NGHTTP2_ERR_CALLBACK_FAILURE; + +- stream->error_code = error_code; + stream->closed = TRUE; + data_s->state.drain++; +- conn->proto.httpc.drain_total++; ++ httpc = &conn->proto.httpc; ++ httpc->drain_total++; ++ httpc->error_code = error_code; + + /* remove the entry from the hash as the stream is now gone */ + nghttp2_session_set_stream_user_data(session, stream_id, 0); +@@ -1223,13 +1225,14 @@ static int h2_session_send(struct Curl_easy *data, + * This function returns 0 if it succeeds, or -1 and error code will + * be assigned to *err. + */ +-static int h2_process_pending_input(struct Curl_easy *data, ++static int h2_process_pending_input(struct connectdata *conn, + struct http_conn *httpc, + CURLcode *err) + { + ssize_t nread; + char *inbuf; + ssize_t rv; ++ struct Curl_easy *data = conn->data; + + nread = httpc->inbuflen - httpc->nread_inbuf; + inbuf = httpc->inbuf + httpc->nread_inbuf; +@@ -1267,7 +1270,13 @@ static int h2_process_pending_input(struct Curl_easy *data, + if(should_close_session(httpc)) { + DEBUGF(infof(data, + "h2_process_pending_input: nothing to do in this session\n")); +- *err = CURLE_HTTP2; ++ if(httpc->error_code) ++ *err = CURLE_HTTP2; ++ else { ++ /* not an error per se, but should still close the connection */ ++ connclose(conn, "GOAWAY received"); ++ *err = CURLE_OK; ++ } + return -1; + } + +@@ -1298,7 +1307,7 @@ CURLcode Curl_http2_done_sending(struct connectdata *conn) + that it can signal EOF to nghttp2 */ + (void)nghttp2_session_resume_data(h2, stream->stream_id); + +- (void)h2_process_pending_input(conn->data, httpc, &result); ++ (void)h2_process_pending_input(conn, httpc, &result); + } + } + return result; +@@ -1322,7 +1331,7 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, + data->state.drain = 0; + + if(httpc->pause_stream_id == 0) { +- if(h2_process_pending_input(data, httpc, err) != 0) { ++ if(h2_process_pending_input(conn, httpc, err) != 0) { + return -1; + } + } +@@ -1331,10 +1340,10 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, + + /* Reset to FALSE to prevent infinite loop in readwrite_data function. */ + stream->closed = FALSE; +- if(stream->error_code != NGHTTP2_NO_ERROR) { ++ if(httpc->error_code != NGHTTP2_NO_ERROR) { + failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)", +- stream->stream_id, Curl_http2_strerror(stream->error_code), +- stream->error_code); ++ stream->stream_id, Curl_http2_strerror(httpc->error_code), ++ httpc->error_code); + *err = CURLE_HTTP2_STREAM; + return -1; + } +@@ -1482,7 +1491,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, + /* We have paused nghttp2, but we have no pause data (see + on_data_chunk_recv). */ + httpc->pause_stream_id = 0; +- if(h2_process_pending_input(data, httpc, &result) != 0) { ++ if(h2_process_pending_input(conn, httpc, &result) != 0) { + *err = result; + return -1; + } +@@ -1512,7 +1521,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, + frames, then we have to call it again with 0-length data. + Without this, on_stream_close callback will not be called, + and stream could be hanged. */ +- if(h2_process_pending_input(data, httpc, &result) != 0) { ++ if(h2_process_pending_input(conn, httpc, &result) != 0) { + *err = result; + return -1; + } +diff --git a/lib/multi.c b/lib/multi.c +index d5bc532..7b9ba61 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -5,7 +5,7 @@ + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * +- * Copyright (C) 1998 - 2017, Daniel Stenberg, , et al. ++ * 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 +@@ -572,11 +572,8 @@ static CURLcode multi_done(struct connectdata **connp, + result = CURLE_ABORTED_BY_CALLBACK; + } + +- if(conn->send_pipe.size + conn->recv_pipe.size != 0 && +- !data->set.reuse_forbid && +- !conn->bits.close) { +- /* Stop if pipeline is not empty and we do not have to close +- connection. */ ++ if(conn->send_pipe.size || conn->recv_pipe.size) { ++ /* Stop if pipeline is not empty . */ + data->easy_conn = NULL; + DEBUGF(infof(data, "Connection still in use, no more multi_done now!\n")); + return CURLE_OK; +-- +2.14.4 + + +From 84ddda3994c1f12d79946780dee9111b3cf1c308 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 19 Apr 2018 20:03:30 +0200 +Subject: [PATCH 2/2] http2: handle GOAWAY properly + +When receiving REFUSED_STREAM, mark the connection for close and retry +streams accordingly on another/fresh connection. + +Reported-by: Terry Wu +Fixes #2416 +Fixes #1618 +Closes #2510 + +Upstream-commit: d122df5972fc01e39ae28e6bca705237d7e3318a +Signed-off-by: Kamil Dudka +--- + lib/http2.c | 17 ++++++++++++----- + lib/multi.c | 4 +++- + lib/transfer.c | 17 +++++++++++++++-- + lib/urldata.h | 2 +- + 4 files changed, 31 insertions(+), 9 deletions(-) + +diff --git a/lib/http2.c b/lib/http2.c +index b2c34e9..fba4d70 100644 +--- a/lib/http2.c ++++ b/lib/http2.c +@@ -1070,7 +1070,6 @@ void Curl_http2_done(struct connectdata *conn, bool premature) + struct http_conn *httpc = &conn->proto.httpc; + + if(http->header_recvbuf) { +- DEBUGF(infof(data, "free header_recvbuf!!\n")); + Curl_add_buffer_free(http->header_recvbuf); + http->header_recvbuf = NULL; /* clear the pointer */ + Curl_add_buffer_free(http->trailer_recvbuf); +@@ -1340,7 +1339,15 @@ static ssize_t http2_handle_stream_close(struct connectdata *conn, + + /* Reset to FALSE to prevent infinite loop in readwrite_data function. */ + stream->closed = FALSE; +- if(httpc->error_code != NGHTTP2_NO_ERROR) { ++ if(httpc->error_code == NGHTTP2_REFUSED_STREAM) { ++ DEBUGF(infof(data, "REFUSED_STREAM (%d), try again on a new connection!\n", ++ stream->stream_id)); ++ connclose(conn, "REFUSED_STREAM"); /* don't use this anymore */ ++ data->state.refused_stream = TRUE; ++ *err = CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */ ++ return -1; ++ } ++ else if(httpc->error_code != NGHTTP2_NO_ERROR) { + failf(data, "HTTP/2 stream %u was not closed cleanly: %s (err %d)", + stream->stream_id, Curl_http2_strerror(httpc->error_code), + httpc->error_code); +@@ -1568,9 +1575,9 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex, + } + + if(nread == 0) { +- failf(data, "Unexpected EOF"); +- *err = CURLE_RECV_ERROR; +- return -1; ++ DEBUGF(infof(data, "end of stream\n")); ++ *err = CURLE_OK; ++ return 0; + } + + DEBUGF(infof(data, "nread=%zd\n", nread)); +diff --git a/lib/multi.c b/lib/multi.c +index 98e5fca..d69e5f9 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -575,7 +575,9 @@ static CURLcode multi_done(struct connectdata **connp, + if(conn->send_pipe.size || conn->recv_pipe.size) { + /* Stop if pipeline is not empty . */ + data->easy_conn = NULL; +- DEBUGF(infof(data, "Connection still in use, no more multi_done now!\n")); ++ DEBUGF(infof(data, "Connection still in use %d/%d, " ++ "no more multi_done now!\n", ++ conn->send_pipe.size, conn->recv_pipe.size)); + return CURLE_OK; + } + +diff --git a/lib/transfer.c b/lib/transfer.c +index fd9af31..5c29cc9 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1896,7 +1896,7 @@ CURLcode Curl_retry_request(struct connectdata *conn, + char **url) + { + struct Curl_easy *data = conn->data; +- ++ bool retry = FALSE; + *url = NULL; + + /* if we're talking upload, we can't do the checks below, unless the protocol +@@ -1909,7 +1909,7 @@ CURLcode Curl_retry_request(struct connectdata *conn, + conn->bits.reuse && + (!data->set.opt_no_body + || (conn->handler->protocol & PROTO_FAMILY_HTTP)) && +- (data->set.rtspreq != RTSPREQ_RECEIVE)) { ++ (data->set.rtspreq != RTSPREQ_RECEIVE)) + /* We got no data, we attempted to re-use a connection. For HTTP this + can be a retry so we try again regardless if we expected a body. + For other protocols we only try again only if we expected a body. +@@ -1917,6 +1917,19 @@ CURLcode Curl_retry_request(struct connectdata *conn, + This might happen if the connection was left alive when we were + done using it before, but that was closed when we wanted to read from + it again. Bad luck. Retry the same request on a fresh connect! */ ++ retry = TRUE; ++ else if(data->state.refused_stream && ++ (data->req.bytecount + data->req.headerbytecount == 0) ) { ++ /* This was sent on a refused stream, safe to rerun. A refused stream ++ error can typically only happen on HTTP/2 level if the stream is safe ++ to issue again, but the nghttp2 API can deliver the message to other ++ streams as well, which is why this adds the check the data counters ++ too. */ ++ infof(conn->data, "REFUSED_STREAM, retrying a fresh connect\n"); ++ data->state.refused_stream = FALSE; /* clear again */ ++ retry = TRUE; ++ } ++ if(retry) { + infof(conn->data, "Connection died, retrying a fresh connect\n"); + *url = strdup(conn->data->change.url); + if(!*url) +diff --git a/lib/urldata.h b/lib/urldata.h +index 3d7b9e5..6a36ee9 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1391,7 +1391,7 @@ struct UrlState { + curl_off_t current_speed; /* the ProgressShow() function sets this, + bytes / second */ + bool this_is_a_follow; /* this is a followed Location: request */ +- ++ bool refused_stream; /* this was refused, try again */ + char *first_host; /* host name of the first (not followed) request. + if set, this should be the host name that we will + sent authorization to, no else. Used to make Location: +-- +2.14.4 + diff --git a/0005-curl-7.55.1-CVE-2017-1000254.patch b/0005-curl-7.55.1-CVE-2017-1000254.patch new file mode 100644 index 0000000..6ee9bb9 --- /dev/null +++ b/0005-curl-7.55.1-CVE-2017-1000254.patch @@ -0,0 +1,136 @@ +From 1e6f9bb225047cb40232ac3e0aa5da161e49d465 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 25 Sep 2017 00:35:22 +0200 +Subject: [PATCH] FTP: zero terminate the entry path even on bad input + +... a single double quote could leave the entry path buffer without a zero +terminating byte. CVE-2017-1000254 + +Test 1152 added to verify. + +Reported-by: Max Dymond +Bug: https://curl.haxx.se/docs/adv_20171004.html + +Upstream-commit: 5ff2c5ff25750aba1a8f64fbcad8e5b891512584 +Signed-off-by: Kamil Dudka +--- + lib/ftp.c | 7 ++++-- + tests/data/Makefile.inc | 1 + + tests/data/test1152 | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 67 insertions(+), 2 deletions(-) + create mode 100644 tests/data/test1152 + +diff --git a/lib/ftp.c b/lib/ftp.c +index 6e86e53..bcba6bb 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -2777,6 +2777,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) + const size_t buf_size = data->set.buffer_size; + char *dir; + char *store; ++ bool entry_extracted = FALSE; + + dir = malloc(nread + 1); + if(!dir) +@@ -2808,7 +2809,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) + } + else { + /* end of path */ +- *store = '\0'; /* zero terminate */ ++ entry_extracted = TRUE; + break; /* get out of this loop */ + } + } +@@ -2817,7 +2818,9 @@ static CURLcode ftp_statemach_act(struct connectdata *conn) + store++; + ptr++; + } +- ++ *store = '\0'; /* zero terminate */ ++ } ++ if(entry_extracted) { + /* If the path name does not look like an absolute path (i.e.: it + does not start with a '/'), we probably need some server-dependent + adjustments. For example, this is the case when connecting to +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index 1657ac6..f8f6e41 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -121,6 +121,7 @@ test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 \ + test1128 test1129 test1130 test1131 test1132 test1133 test1134 test1135 \ + test1136 test1137 test1138 test1139 test1140 test1141 test1142 test1143 \ + test1144 test1145 test1146 test1147 test1148 \ ++test1152 \ + 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/test1152 b/tests/data/test1152 +new file mode 100644 +index 0000000..aa8c0a7 +--- /dev/null ++++ b/tests/data/test1152 +@@ -0,0 +1,61 @@ ++ ++ ++ ++FTP ++PASV ++LIST ++ ++ ++# ++# Server-side ++ ++ ++REPLY PWD 257 "just one ++ ++ ++# When doing LIST, we get the default list output hard-coded in the test ++# FTP server ++ ++total 20 ++drwxr-xr-x 8 98 98 512 Oct 22 13:06 . ++drwxr-xr-x 8 98 98 512 Oct 22 13:06 .. ++drwxr-xr-x 2 98 98 512 May 2 1996 curl-releases ++-r--r--r-- 1 0 1 35 Jul 16 1996 README ++lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin ++dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev ++drwxrwxrwx 2 98 98 512 May 29 16:04 download.html ++dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc ++drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub ++dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr ++ ++ ++ ++# ++# Client-side ++ ++ ++ftp ++ ++ ++FTP with uneven quote in PWD response ++ ++ ++ftp://%HOSTIP:%FTPPORT/test-1152/ ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++USER anonymous ++PASS ftp@example.com ++PWD ++CWD test-1152 ++EPSV ++TYPE A ++LIST ++QUIT ++ ++ ++ +-- +2.13.6 + diff --git a/0006-curl-7.55.1-CVE-2017-1000257.patch b/0006-curl-7.55.1-CVE-2017-1000257.patch new file mode 100644 index 0000000..01b2d6f --- /dev/null +++ b/0006-curl-7.55.1-CVE-2017-1000257.patch @@ -0,0 +1,36 @@ +From f8b7620e0578ef44e8fd958d32f348b535d1ab77 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 7 Oct 2017 00:11:31 +0200 +Subject: [PATCH] imap: if a FETCH response has no size, don't call write + callback + +CVE-2017-1000257 + +Reported-by: Brian Carpenter and 0xd34db347 +Also detected by OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3586 + +Upstream-commit: 13c9a9ded3ae744a1e11cbc14e9146d9fa427040 +Signed-off-by: Kamil Dudka +--- + lib/imap.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/lib/imap.c b/lib/imap.c +index 48af290..4deba88 100644 +--- a/lib/imap.c ++++ b/lib/imap.c +@@ -1091,6 +1091,11 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, + /* The conversion from curl_off_t to size_t is always fine here */ + chunk = (size_t)size; + ++ if(!chunk) { ++ /* no size, we're done with the data */ ++ state(conn, IMAP_STOP); ++ return CURLE_OK; ++ } + result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk); + if(result) + return result; +-- +2.13.6 + diff --git a/0007-curl-7.55.1-CVE-2017-8817.patch b/0007-curl-7.55.1-CVE-2017-8817.patch new file mode 100644 index 0000000..99453ce --- /dev/null +++ b/0007-curl-7.55.1-CVE-2017-8817.patch @@ -0,0 +1,132 @@ +From d288bcc0635f154fa2167bb0ac1de554bde971b6 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 10 Nov 2017 08:52:45 +0100 +Subject: [PATCH] wildcardmatch: fix heap buffer overflow in setcharset + +The code would previous read beyond the end of the pattern string if the +match pattern ends with an open bracket when the default pattern +matching function is used. + +Detected by OSS-Fuzz: +https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=4161 + +CVE-2017-8817 + +Bug: https://curl.haxx.se/docs/adv_2017-ae72.html + +Upstream-commit: 0b664ba968437715819bfe4c7ada5679d16ebbc3 +Signed-off-by: Kamil Dudka +--- + lib/curl_fnmatch.c | 9 +++------ + tests/data/Makefile.inc | 1 + + tests/data/test1163 | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 56 insertions(+), 6 deletions(-) + create mode 100644 tests/data/test1163 + +diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c +index 46d3ada..5dd5323 100644 +--- a/lib/curl_fnmatch.c ++++ b/lib/curl_fnmatch.c +@@ -133,6 +133,9 @@ static int setcharset(unsigned char **p, unsigned char *charset) + unsigned char c; + for(;;) { + c = **p; ++ if(!c) ++ return SETCHARSET_FAIL; ++ + switch(state) { + case CURLFNM_SCHS_DEFAULT: + if(ISALNUM(c)) { /* ASCII value */ +@@ -196,9 +199,6 @@ static int setcharset(unsigned char **p, unsigned char *charset) + else + return SETCHARSET_FAIL; + } +- else if(c == '\0') { +- return SETCHARSET_FAIL; +- } + else { + charset[c] = 1; + (*p)++; +@@ -277,9 +277,6 @@ static int setcharset(unsigned char **p, unsigned char *charset) + else if(c == ']') { + return SETCHARSET_OK; + } +- else if(c == '\0') { +- return SETCHARSET_FAIL; +- } + else if(ISPRINT(c)) { + charset[c] = 1; + (*p)++; +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index f8f6e41..6e2f402 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -122,6 +122,7 @@ test1128 test1129 test1130 test1131 test1132 test1133 test1134 test1135 \ + test1136 test1137 test1138 test1139 test1140 test1141 test1142 test1143 \ + test1144 test1145 test1146 test1147 test1148 \ + test1152 \ ++test1163 \ + 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/test1163 b/tests/data/test1163 +new file mode 100644 +index 0000000..a109b51 +--- /dev/null ++++ b/tests/data/test1163 +@@ -0,0 +1,52 @@ ++ ++ ++ ++FTP ++RETR ++LIST ++wildcardmatch ++ftplistparser ++flaky ++ ++ ++ ++# ++# Server-side ++ ++ ++ ++ ++ ++# Client-side ++ ++ ++ftp ++ ++ ++lib576 ++ ++ ++FTP wildcard with pattern ending with an open-bracket ++ ++ ++"ftp://%HOSTIP:%FTPPORT/fully_simulated/DOS/*[][" ++ ++ ++ ++ ++USER anonymous ++PASS ftp@example.com ++PWD ++CWD fully_simulated ++CWD DOS ++EPSV ++TYPE A ++LIST ++QUIT ++ ++# 78 == CURLE_REMOTE_FILE_NOT_FOUND ++ ++78 ++ ++ ++ +-- +2.13.6 + diff --git a/0008-curl-7.55.1-CVE-2017-8816.patch b/0008-curl-7.55.1-CVE-2017-8816.patch new file mode 100644 index 0000000..374d79d --- /dev/null +++ b/0008-curl-7.55.1-CVE-2017-8816.patch @@ -0,0 +1,61 @@ +From 300d6e1b2598dc34004e4608e6718f1c0c206110 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 6 Nov 2017 23:51:52 +0100 +Subject: [PATCH] ntlm: avoid integer overflow for malloc size + +Reported-by: Alex Nichols +Assisted-by: Kamil Dudka and Max Dymond + +CVE-2017-8816 + +Bug: https://curl.haxx.se/docs/adv_2017-11e7.html + +Upstream-commit: 7f2a1df6f5fc598750b2c6f34465c8d924db28cc +Signed-off-by: Kamil Dudka +--- + lib/curl_ntlm_core.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c +index aea5452..eb44f97 100644 +--- a/lib/curl_ntlm_core.c ++++ b/lib/curl_ntlm_core.c +@@ -622,6 +622,12 @@ CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, + return CURLE_OK; + } + ++#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4) ++#define SIZE_T_MAX 18446744073709551615U ++#else ++#define SIZE_T_MAX 4294967295U ++#endif ++ + /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode + * (uppercase UserName + Domain) as the data + */ +@@ -631,10 +637,20 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, + unsigned char *ntlmv2hash) + { + /* Unicode representation */ +- size_t identity_len = (userlen + domlen) * 2; +- unsigned char *identity = malloc(identity_len); ++ size_t identity_len; ++ unsigned char *identity; + CURLcode result = CURLE_OK; + ++ /* we do the length checks below separately to avoid integer overflow risk ++ on extreme data lengths */ ++ if((userlen > SIZE_T_MAX/2) || ++ (domlen > SIZE_T_MAX/2) || ++ ((userlen + domlen) > SIZE_T_MAX/2)) ++ return CURLE_OUT_OF_MEMORY; ++ ++ identity_len = (userlen + domlen) * 2; ++ identity = malloc(identity_len); ++ + if(!identity) + return CURLE_OUT_OF_MEMORY; + +-- +2.13.6 + diff --git a/0009-curl-7.55.1-CVE-2018-1000007.patch b/0009-curl-7.55.1-CVE-2018-1000007.patch new file mode 100644 index 0000000..0720745 --- /dev/null +++ b/0009-curl-7.55.1-CVE-2018-1000007.patch @@ -0,0 +1,330 @@ +From e6968d1d220891230bcca5340bfd364183ceaa31 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 19 Jan 2018 13:19:25 +0100 +Subject: [PATCH] http: prevent custom Authorization headers in redirects + +... unless CURLOPT_UNRESTRICTED_AUTH is set to allow them. This matches how +curl already handles Authorization headers created internally. + +Note: this changes behavior slightly, for the sake of reducing mistakes. + +Added test 317 and 318 to verify. + +Reported-by: Craig de Stigter +Bug: https://curl.haxx.se/docs/adv_2018-b3bf.html + +Upstream-commit: af32cd3859336ab963591ca0df9b1e33a7ee066b +Signed-off-by: Kamil Dudka +--- + docs/libcurl/opts/CURLOPT_HTTPHEADER.3 | 12 ++++- + lib/http.c | 10 +++- + lib/url.c | 2 +- + lib/urldata.h | 2 +- + tests/data/Makefile.inc | 2 +- + tests/data/test317 | 94 +++++++++++++++++++++++++++++++++ + tests/data/test318 | 95 ++++++++++++++++++++++++++++++++++ + 7 files changed, 212 insertions(+), 5 deletions(-) + create mode 100644 tests/data/test317 + create mode 100644 tests/data/test318 + +diff --git a/docs/libcurl/opts/CURLOPT_HTTPHEADER.3 b/docs/libcurl/opts/CURLOPT_HTTPHEADER.3 +index 6aeec22..781e570 100644 +--- a/docs/libcurl/opts/CURLOPT_HTTPHEADER.3 ++++ b/docs/libcurl/opts/CURLOPT_HTTPHEADER.3 +@@ -5,7 +5,7 @@ + .\" * | (__| |_| | _ <| |___ + .\" * \___|\___/|_| \_\_____| + .\" * +-.\" * Copyright (C) 1998 - 2015, Daniel Stenberg, , et al. ++.\" * 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 +@@ -78,6 +78,16 @@ the headers. They may be private or otherwise sensitive to leak. + + Use \fICURLOPT_HEADEROPT(3)\fP to make the headers only get sent to where you + intend them to get sent. ++ ++Custom headers are sent in all requests done by the easy handles, which ++implies that if you tell libcurl to follow redirects ++(\fICURLOPT_FOLLOWLOCATION(3)\fP), the same set of custom headers will be sent ++in the subsequent request. Redirects can of course go to other hosts and thus ++those servers will get all the contents of your custom headers too. ++ ++Starting in 7.58.0, libcurl will specifically prevent "Authorization:" headers ++from being sent to other hosts than the first used one, unless specifically ++permitted with the \fICURLOPT_UNRESTRICTED_AUTH(3)\fP option. + .SH DEFAULT + NULL + .SH PROTOCOLS +diff --git a/lib/http.c b/lib/http.c +index b73e58c..c15208d 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -732,7 +732,7 @@ Curl_http_output_auth(struct connectdata *conn, + if(!data->state.this_is_a_follow || + conn->bits.netrc || + !data->state.first_host || +- data->set.http_disable_hostname_check_before_authentication || ++ data->set.allow_auth_to_other_hosts || + strcasecompare(data->state.first_host, conn->host.name)) { + result = output_auth_headers(conn, authhost, request, path, FALSE); + } +@@ -1651,6 +1651,14 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn, + checkprefix("Transfer-Encoding:", headers->data)) + /* HTTP/2 doesn't support chunked requests */ + ; ++ else if(checkprefix("Authorization:", headers->data) && ++ /* be careful of sending this potentially sensitive header to ++ other hosts */ ++ (data->state.this_is_a_follow && ++ data->state.first_host && ++ !data->set.allow_auth_to_other_hosts && ++ !strcasecompare(data->state.first_host, conn->host.name))) ++ ; + else { + CURLcode result = Curl_add_bufferf(req_buffer, "%s\r\n", + headers->data); +diff --git a/lib/url.c b/lib/url.c +index 71d4d8b..ba53131 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -1008,7 +1008,7 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option, + * Send authentication (user+password) when following locations, even when + * hostname changed. + */ +- data->set.http_disable_hostname_check_before_authentication = ++ data->set.allow_auth_to_other_hosts = + (0 != va_arg(param, long)) ? TRUE : FALSE; + break; + +diff --git a/lib/urldata.h b/lib/urldata.h +index b4f18e7..1dd62ae 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1757,7 +1757,7 @@ struct UserDefined { + bool http_keep_sending_on_error; /* for HTTP status codes >= 300 */ + bool http_follow_location; /* follow HTTP redirects */ + bool http_transfer_encoding; /* request compressed HTTP transfer-encoding */ +- bool http_disable_hostname_check_before_authentication; ++ bool allow_auth_to_other_hosts; + bool include_header; /* include received protocol headers in data output */ + bool http_set_referer; /* is a custom referer used */ + bool http_auto_referer; /* set "correct" referer when following location: */ +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index 6e2f402..870d0da 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -55,7 +55,7 @@ test280 test281 test282 test283 test284 test285 test286 test287 test288 \ + test289 test290 test291 test292 test293 test294 test295 test296 test297 \ + test298 test299 test300 test301 test302 test303 test304 test305 test306 \ + test307 test308 test309 test310 test311 test312 test313 \ +- test320 test321 test322 test323 test324 \ ++ test317 test318 test320 test321 test322 test323 test324 \ + test325 \ + test350 test351 test352 test353 test354 \ + \ +diff --git a/tests/data/test317 b/tests/data/test317 +new file mode 100644 +index 0000000..c6d8697 +--- /dev/null ++++ b/tests/data/test317 +@@ -0,0 +1,94 @@ ++ ++ ++ ++HTTP ++HTTP proxy ++HTTP Basic auth ++HTTP proxy Basic auth ++followlocation ++ ++ ++# ++# Server-side ++ ++ ++HTTP/1.1 302 OK ++Date: Thu, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake swsclose ++Content-Type: text/html ++Funny-head: yesyes ++Location: http://goto.second.host.now/3170002 ++Content-Length: 8 ++Connection: close ++ ++contents ++ ++ ++HTTP/1.1 200 OK ++Date: Thu, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake swsclose ++Content-Type: text/html ++Funny-head: yesyes ++Content-Length: 9 ++ ++contents ++ ++ ++ ++HTTP/1.1 302 OK ++Date: Thu, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake swsclose ++Content-Type: text/html ++Funny-head: yesyes ++Location: http://goto.second.host.now/3170002 ++Content-Length: 8 ++Connection: close ++ ++HTTP/1.1 200 OK ++Date: Thu, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake swsclose ++Content-Type: text/html ++Funny-head: yesyes ++Content-Length: 9 ++ ++contents ++ ++ ++ ++# ++# Client-side ++ ++ ++http ++ ++ ++HTTP with custom Authorization: and redirect to new host ++ ++ ++http://first.host.it.is/we/want/that/page/317 -x %HOSTIP:%HTTPPORT -H "Authorization: s3cr3t" --proxy-user testing:this --location ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++^User-Agent:.* ++ ++ ++GET http://first.host.it.is/we/want/that/page/317 HTTP/1.1 ++Host: first.host.it.is ++Proxy-Authorization: Basic dGVzdGluZzp0aGlz ++Accept: */* ++Proxy-Connection: Keep-Alive ++Authorization: s3cr3t ++ ++GET http://goto.second.host.now/3170002 HTTP/1.1 ++Host: goto.second.host.now ++Proxy-Authorization: Basic dGVzdGluZzp0aGlz ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++ ++ ++ +diff --git a/tests/data/test318 b/tests/data/test318 +new file mode 100644 +index 0000000..838d1ba +--- /dev/null ++++ b/tests/data/test318 +@@ -0,0 +1,95 @@ ++ ++ ++ ++HTTP ++HTTP proxy ++HTTP Basic auth ++HTTP proxy Basic auth ++followlocation ++ ++ ++# ++# Server-side ++ ++ ++HTTP/1.1 302 OK ++Date: Thu, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake swsclose ++Content-Type: text/html ++Funny-head: yesyes ++Location: http://goto.second.host.now/3180002 ++Content-Length: 8 ++Connection: close ++ ++contents ++ ++ ++HTTP/1.1 200 OK ++Date: Thu, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake swsclose ++Content-Type: text/html ++Funny-head: yesyes ++Content-Length: 9 ++ ++contents ++ ++ ++ ++HTTP/1.1 302 OK ++Date: Thu, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake swsclose ++Content-Type: text/html ++Funny-head: yesyes ++Location: http://goto.second.host.now/3180002 ++Content-Length: 8 ++Connection: close ++ ++HTTP/1.1 200 OK ++Date: Thu, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake swsclose ++Content-Type: text/html ++Funny-head: yesyes ++Content-Length: 9 ++ ++contents ++ ++ ++ ++# ++# Client-side ++ ++ ++http ++ ++ ++HTTP with custom Authorization: and redirect to new host ++ ++ ++http://first.host.it.is/we/want/that/page/318 -x %HOSTIP:%HTTPPORT -H "Authorization: s3cr3t" --proxy-user testing:this --location-trusted ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++^User-Agent:.* ++ ++ ++GET http://first.host.it.is/we/want/that/page/318 HTTP/1.1 ++Host: first.host.it.is ++Proxy-Authorization: Basic dGVzdGluZzp0aGlz ++Accept: */* ++Proxy-Connection: Keep-Alive ++Authorization: s3cr3t ++ ++GET http://goto.second.host.now/3180002 HTTP/1.1 ++Host: goto.second.host.now ++Proxy-Authorization: Basic dGVzdGluZzp0aGlz ++Accept: */* ++Proxy-Connection: Keep-Alive ++Authorization: s3cr3t ++ ++ ++ ++ +-- +2.13.6 + diff --git a/0010-curl-7.55.1-CVE-2018-1000005.patch b/0010-curl-7.55.1-CVE-2018-1000005.patch new file mode 100644 index 0000000..9b8bdf6 --- /dev/null +++ b/0010-curl-7.55.1-CVE-2018-1000005.patch @@ -0,0 +1,42 @@ +From cbe5cf0d95a0227739bd2126d5fa411d084e1af2 Mon Sep 17 00:00:00 2001 +From: Zhouyihai Ding +Date: Wed, 10 Jan 2018 10:12:18 -0800 +Subject: [PATCH] http2: fix incorrect trailer buffer size + +Prior to this change the stored byte count of each trailer was +miscalculated and 1 less than required. It appears any trailer +after the first that was passed to Curl_client_write would be truncated +or corrupted as well as the size. Potentially the size of some +subsequent trailer could be erroneously extracted from the contents of +that trailer, and since that size is used by client write an +out-of-bounds read could occur and cause a crash or be otherwise +processed by client write. + +The bug appears to have been born in 0761a51 (precedes 7.49.0). + +Closes https://github.com/curl/curl/pull/2231 + +Upstream-commit: fa3dbb9a147488a2943bda809c66fc497efe06cb +Signed-off-by: Kamil Dudka +--- + lib/http2.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/http2.c b/lib/http2.c +index 0e55801..3d7610d 100644 +--- a/lib/http2.c ++++ b/lib/http2.c +@@ -926,8 +926,8 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, + + if(stream->bodystarted) { + /* This is trailer fields. */ +- /* 3 is for ":" and "\r\n". */ +- uint32_t n = (uint32_t)(namelen + valuelen + 3); ++ /* 4 is for ": " and "\r\n". */ ++ uint32_t n = (uint32_t)(namelen + valuelen + 4); + + DEBUGF(infof(data_s, "h2 trailer: %.*s: %.*s\n", namelen, name, valuelen, + value)); +-- +2.13.6 + diff --git a/0016-curl-7.55.1-CVE-2018-1000122.patch b/0016-curl-7.55.1-CVE-2018-1000122.patch new file mode 100644 index 0000000..14ac23f --- /dev/null +++ b/0016-curl-7.55.1-CVE-2018-1000122.patch @@ -0,0 +1,41 @@ +From fffbdcf516a527482095eac30baa27b78c2dbaa2 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 8 Mar 2018 10:33:16 +0100 +Subject: [PATCH] readwrite: make sure excess reads don't go beyond buffer end + +CVE-2018-1000122 +Bug: https://curl.haxx.se/docs/adv_2018-b047.html + +Detected by OSS-fuzz + +Upstream-commit: d52dc4760f6d9ca1937eefa2093058a952465128 +Signed-off-by: Kamil Dudka +--- + lib/transfer.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/lib/transfer.c b/lib/transfer.c +index 3537b58..bc3b39b 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -788,10 +788,15 @@ static CURLcode readwrite_data(struct Curl_easy *data, + + } /* if(!header and data to read) */ + +- if(conn->handler->readwrite && +- (excess > 0 && !conn->bits.stream_was_rewound)) { ++ if(conn->handler->readwrite && excess && !conn->bits.stream_was_rewound) { + /* Parse the excess data */ + k->str += nread; ++ ++ if(&k->str[excess] > &k->buf[data->set.buffer_size]) { ++ /* the excess amount was too excessive(!), make sure ++ it doesn't read out of buffer */ ++ excess = &k->buf[data->set.buffer_size] - k->str; ++ } + nread = (ssize_t)excess; + + result = conn->handler->readwrite(data, conn, &nread, &readmore); +-- +2.14.3 + diff --git a/0017-curl-7.55.1-CVE-2018-1000121.patch b/0017-curl-7.55.1-CVE-2018-1000121.patch new file mode 100644 index 0000000..aa84a7b --- /dev/null +++ b/0017-curl-7.55.1-CVE-2018-1000121.patch @@ -0,0 +1,45 @@ +From 1d7bcc866591aba5788dc6c701ef8b564d09e329 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 6 Mar 2018 23:02:16 +0100 +Subject: [PATCH] openldap: check ldap_get_attribute_ber() results for NULL + before using + +CVE-2018-1000121 +Reported-by: Dario Weisser +Bug: https://curl.haxx.se/docs/adv_2018-97a2.html + +Upstream-commit: 9889db043393092e9d4b5a42720bba0b3d58deba +Signed-off-by: Kamil Dudka +--- + lib/openldap.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/lib/openldap.c b/lib/openldap.c +index 369309c..d71946d 100644 +--- a/lib/openldap.c ++++ b/lib/openldap.c +@@ -445,7 +445,7 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, + + for(ent = ldap_first_message(li->ld, msg); ent; + ent = ldap_next_message(li->ld, ent)) { +- struct berval bv, *bvals, **bvp = &bvals; ++ struct berval bv, *bvals; + int binary = 0, msgtype; + CURLcode writeerr; + +@@ -507,9 +507,9 @@ static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf, + } + data->req.bytecount += bv.bv_len + 5; + +- for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp); +- rc == LDAP_SUCCESS; +- rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) { ++ for(rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals); ++ (rc == LDAP_SUCCESS) && bvals; ++ rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, &bvals)) { + int i; + + if(bv.bv_val == NULL) break; +-- +2.14.3 + diff --git a/0018-curl-7.55.1-CVE-2018-1000120.patch b/0018-curl-7.55.1-CVE-2018-1000120.patch new file mode 100644 index 0000000..3e55578 --- /dev/null +++ b/0018-curl-7.55.1-CVE-2018-1000120.patch @@ -0,0 +1,302 @@ +From 5452fdc5ae93f3571074c591fdf28cdf630796a0 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 12 Sep 2017 09:29:01 +0200 +Subject: [PATCH 1/2] FTP: URL decode path for dir listing in nocwd mode + +Reported-by: Zenju on github + +Test 244 added to verify +Fixes #1974 +Closes #1976 + +Upstream-commit: ecf21c551fa3426579463abe34b623111b8d487c +Signed-off-by: Kamil Dudka +--- + lib/ftp.c | 29 ++++++++++++-------------- + tests/data/Makefile.inc | 2 +- + tests/data/test244 | 54 +++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 68 insertions(+), 17 deletions(-) + create mode 100644 tests/data/test244 + +diff --git a/lib/ftp.c b/lib/ftp.c +index bcba6bb..fb3a716 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -975,7 +975,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, + char *port_start = NULL; + char *port_sep = NULL; + +- addr = calloc(addrlen+1, 1); ++ addr = calloc(addrlen + 1, 1); + if(!addr) + return CURLE_OUT_OF_MEMORY; + +@@ -1018,7 +1018,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn, + if(ip_end != NULL) { + port_start = strchr(ip_end, ':'); + if(port_start) { +- port_min = curlx_ultous(strtoul(port_start+1, NULL, 10)); ++ port_min = curlx_ultous(strtoul(port_start + 1, NULL, 10)); + port_sep = strchr(port_start, '-'); + if(port_sep) { + port_max = curlx_ultous(strtoul(port_sep + 1, NULL, 10)); +@@ -1457,25 +1457,22 @@ static CURLcode ftp_state_list(struct connectdata *conn) + then just do LIST (in that case: nothing to do here) + */ + char *cmd, *lstArg, *slashPos; ++ const char *inpath = data->state.path; + + lstArg = NULL; + if((data->set.ftp_filemethod == FTPFILE_NOCWD) && +- data->state.path && +- data->state.path[0] && +- strchr(data->state.path, '/')) { +- +- lstArg = strdup(data->state.path); +- if(!lstArg) +- return CURLE_OUT_OF_MEMORY; ++ inpath && inpath[0] && strchr(inpath, '/')) { ++ size_t n = strlen(inpath); + + /* Check if path does not end with /, as then we cut off the file part */ +- if(lstArg[strlen(lstArg) - 1] != '/') { +- ++ if(inpath[n - 1] != '/') { + /* chop off the file part if format is dir/dir/file */ +- slashPos = strrchr(lstArg, '/'); +- if(slashPos) +- *(slashPos+1) = '\0'; ++ slashPos = strrchr(inpath, '/'); ++ n = slashPos - inpath; + } ++ result = Curl_urldecode(data, inpath, n, &lstArg, NULL, FALSE); ++ if(result) ++ return result; + } + + cmd = aprintf("%s%s%s", +@@ -3497,7 +3494,7 @@ static CURLcode ftp_range(struct connectdata *conn) + } + else { + /* X-Y */ +- data->req.maxdownload = (to-from)+1; /* include last byte */ ++ data->req.maxdownload = (to - from) + 1; /* include last byte */ + data->state.resume_from = from; + DEBUGF(infof(conn->data, "FTP RANGE from %" CURL_FORMAT_CURL_OFF_T + " getting %" CURL_FORMAT_CURL_OFF_T " bytes\n", +@@ -4196,7 +4193,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) + return result; + } + ftpc->dirdepth = 1; /* we consider it to be a single dir */ +- filename = slash_pos ? slash_pos+1 : cur_pos; /* rest is file name */ ++ filename = slash_pos ? slash_pos + 1 : cur_pos; /* rest is file name */ + } + else + filename = cur_pos; /* this is a file name only */ +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index 870d0da..d95101b 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -47,7 +47,7 @@ test208 test209 test210 test211 test212 test213 test214 test215 test216 \ + test217 test218 test219 test220 test221 test222 test223 test224 test225 \ + test226 test227 test228 test229 test231 test233 test234 \ + test235 test236 test237 test238 test239 test240 test241 test242 test243 \ +- test245 test246 test247 test248 test249 test250 test251 test252 \ ++test244 test245 test246 test247 test248 test249 test250 test251 test252 \ + test253 test254 test255 test256 test257 test258 test259 test260 test261 \ + test262 test263 test264 test265 test266 test267 test268 test269 test270 \ + test271 test272 test273 test274 test275 test276 test277 test278 test279 \ +diff --git a/tests/data/test244 b/tests/data/test244 +new file mode 100644 +index 0000000..8ce4b63 +--- /dev/null ++++ b/tests/data/test244 +@@ -0,0 +1,54 @@ ++ ++ ++ ++FTP ++PASV ++CWD ++--ftp-method ++nocwd ++ ++ ++# ++# Server-side ++ ++ ++total 20 ++drwxr-xr-x 8 98 98 512 Oct 22 13:06 . ++drwxr-xr-x 8 98 98 512 Oct 22 13:06 .. ++drwxr-xr-x 2 98 98 512 May 2 1996 .NeXT ++-r--r--r-- 1 0 1 35 Jul 16 1996 README ++lrwxrwxrwx 1 0 1 7 Dec 9 1999 bin -> usr/bin ++dr-xr-xr-x 2 0 1 512 Oct 1 1997 dev ++drwxrwxrwx 2 98 98 512 May 29 16:04 download.html ++dr-xr-xr-x 2 0 1 512 Nov 30 1995 etc ++drwxrwxrwx 2 98 1 512 Oct 30 14:33 pub ++dr-xr-xr-x 5 0 1 512 Oct 1 1997 usr ++ ++ ++ ++# Client-side ++ ++ ++ftp ++ ++ ++FTP dir listing with nocwd and URL encoded path ++ ++ ++--ftp-method nocwd ftp://%HOSTIP:%FTPPORT/fir%23t/th%69rd/244/ ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++USER anonymous ++PASS ftp@example.com ++PWD ++EPSV ++TYPE A ++LIST fir#t/third/244/ ++QUIT ++ ++ ++ +-- +2.14.3 + + +From 9534442aae1da4e6cf2ce815e47dbcd82695c3d4 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Wed, 31 Jan 2018 08:40:11 +0100 +Subject: [PATCH 2/2] FTP: reject path components with control codes + +Refuse to operate when given path components featuring byte values lower +than 32. + +Previously, inserting a %00 sequence early in the directory part when +using the 'singlecwd' ftp method could make curl write a zero byte +outside of the allocated buffer. + +Test case 340 verifies. + +CVE-2018-1000120 +Reported-by: Duy Phan Thanh +Bug: https://curl.haxx.se/docs/adv_2018-9cd6.html + +Upstream-commit: 535432c0adb62fe167ec09621500470b6fa4eb0f +Signed-off-by: Kamil Dudka +--- + lib/ftp.c | 8 ++++---- + tests/data/Makefile.inc | 3 +++ + tests/data/test340 | 40 ++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 47 insertions(+), 4 deletions(-) + create mode 100644 tests/data/test340 + +diff --git a/lib/ftp.c b/lib/ftp.c +index fb3a716..268efdd 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -1470,7 +1470,7 @@ static CURLcode ftp_state_list(struct connectdata *conn) + slashPos = strrchr(inpath, '/'); + n = slashPos - inpath; + } +- result = Curl_urldecode(data, inpath, n, &lstArg, NULL, FALSE); ++ result = Curl_urldecode(data, inpath, n, &lstArg, NULL, TRUE); + if(result) + return result; + } +@@ -3183,7 +3183,7 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status, + + if(!result) + /* get the "raw" path */ +- result = Curl_urldecode(data, path_to_use, 0, &path, NULL, FALSE); ++ result = Curl_urldecode(data, path_to_use, 0, &path, NULL, TRUE); + if(result) { + /* We can limp along anyway (and should try to since we may already be in + * the error path) */ +@@ -4187,7 +4187,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) + result = Curl_urldecode(conn->data, slash_pos ? cur_pos : "/", + slash_pos ? dirlen : 1, + &ftpc->dirs[0], NULL, +- FALSE); ++ TRUE); + if(result) { + freedirs(ftpc); + return result; +@@ -4294,7 +4294,7 @@ CURLcode ftp_parse_url_path(struct connectdata *conn) + size_t dlen; + char *path; + CURLcode result = +- Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, FALSE); ++ Curl_urldecode(conn->data, data->state.path, 0, &path, &dlen, TRUE); + if(result) { + freedirs(ftpc); + return result; +diff --git a/tests/data/Makefile.inc b/tests/data/Makefile.inc +index d95101b..af41634 100644 +--- a/tests/data/Makefile.inc ++++ b/tests/data/Makefile.inc +@@ -57,6 +57,9 @@ test298 test299 test300 test301 test302 test303 test304 test305 test306 \ + test307 test308 test309 test310 test311 test312 test313 \ + test317 test318 test320 test321 test322 test323 test324 \ + test325 \ ++\ ++test340 \ ++\ + test350 test351 test352 test353 test354 \ + \ + test400 test401 test402 test403 test404 test405 test406 test407 test408 \ +diff --git a/tests/data/test340 b/tests/data/test340 +new file mode 100644 +index 0000000..d834d76 +--- /dev/null ++++ b/tests/data/test340 +@@ -0,0 +1,40 @@ ++ ++ ++ ++FTP ++PASV ++CWD ++--ftp-method ++singlecwd ++ ++ ++# ++# Server-side ++ ++ ++ ++# Client-side ++ ++ ++ftp ++ ++ ++FTP using %00 in path with singlecwd ++ ++ ++--ftp-method singlecwd ftp://%HOSTIP:%FTPPORT/%00first/second/third/340 ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++USER anonymous ++PASS ftp@example.com ++PWD ++ ++ ++3 ++ ++ ++ +-- +2.14.3 + diff --git a/0019-curl-7.55.1-CVE-2018-1000301.patch b/0019-curl-7.55.1-CVE-2018-1000301.patch new file mode 100644 index 0000000..f72401b --- /dev/null +++ b/0019-curl-7.55.1-CVE-2018-1000301.patch @@ -0,0 +1,48 @@ +From 5815730864a2010872840bae24797983e892eb90 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 24 Mar 2018 23:47:41 +0100 +Subject: [PATCH 1/2] http: restore buffer pointer when bad response-line is + parsed + +... leaving the k->str could lead to buffer over-reads later on. + +CVE: CVE-2018-1000301 +Assisted-by: Max Dymond + +Detected by OSS-Fuzz. +Bug: https://curl.haxx.se/docs/adv_2018-b138.html +Bug: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=7105 + +Upstream-commit: 8c7b3737d29ed5c0575bf592063de8a51450812d +Signed-off-by: Kamil Dudka +--- + lib/http.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/lib/http.c b/lib/http.c +index 841f6cc..dc10f5f 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -2944,6 +2944,8 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, + { + CURLcode result; + struct SingleRequest *k = &data->req; ++ ssize_t onread = *nread; ++ char *ostr = k->str; + + /* header line within buffer loop */ + do { +@@ -3008,7 +3010,9 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data, + else { + /* this was all we read so it's all a bad header */ + k->badheader = HEADER_ALLBAD; +- *nread = (ssize_t)rest_length; ++ *nread = onread; ++ k->str = ostr; ++ return CURLE_OK; + } + break; + } +-- +2.14.3 + diff --git a/0020-curl-7.55.1-CVE-2018-1000300.patch b/0020-curl-7.55.1-CVE-2018-1000300.patch new file mode 100644 index 0000000..0dc80c5 --- /dev/null +++ b/0020-curl-7.55.1-CVE-2018-1000300.patch @@ -0,0 +1,39 @@ +From 9b757a9a431f6859807d9f6e697cc2d2a120098d Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 23 Mar 2018 23:30:04 +0100 +Subject: [PATCH 2/2] pingpong: fix response cache memcpy overflow + +Response data for a handle with a large buffer might be cached and then +used with the "closure" handle when it has a smaller buffer and then the +larger cache will be copied and overflow the new smaller heap based +buffer. + +Reported-by: Dario Weisser +CVE: CVE-2018-1000300 +Bug: https://curl.haxx.se/docs/adv_2018-82c2.html + +Upstream-commit: 583b42cb3b809b1bf597af160468ccba728c2248 +Signed-off-by: Kamil Dudka +--- + lib/pingpong.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/lib/pingpong.c b/lib/pingpong.c +index 438856a..ad370ee 100644 +--- a/lib/pingpong.c ++++ b/lib/pingpong.c +@@ -297,7 +297,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd, + * it would have been populated with something of size int to begin + * with, even though its datatype may be larger than an int. + */ +- DEBUGASSERT((ptr+pp->cache_size) <= (buf+data->set.buffer_size+1)); ++ if((ptr + pp->cache_size) > (buf + data->set.buffer_size + 1)) { ++ failf(data, "cached response data too big to handle"); ++ return CURLE_RECV_ERROR; ++ } + memcpy(ptr, pp->cache, pp->cache_size); + gotbytes = (ssize_t)pp->cache_size; + free(pp->cache); /* free the cache */ +-- +2.14.3 + diff --git a/0021-curl-7.55.1-pkcs11.patch b/0021-curl-7.55.1-pkcs11.patch new file mode 100644 index 0000000..1e00b6d --- /dev/null +++ b/0021-curl-7.55.1-pkcs11.patch @@ -0,0 +1,225 @@ +From 1b9c12b59b582d5366d9a11198631be54c94e440 Mon Sep 17 00:00:00 2001 +From: Anderson Toshiyuki Sasaki +Date: Mon, 19 Feb 2018 14:31:06 +0100 +Subject: [PATCH] ssl: set engine implicitly when a PKCS#11 URI is provided + +This allows the use of PKCS#11 URI for certificates and keys without +setting the corresponding type as "ENG" and the engine as "pkcs11" +explicitly. If a PKCS#11 URI is provided for certificate, key, +proxy_certificate or proxy_key, the corresponding type is set as "ENG" +if not provided and the engine is set to "pkcs11" if not provided. + +Acked-by: Nikos Mavrogiannopoulos +Closes #2333 + +Upstream-commit: 298d2565e2a2f06a859b7f5a1cc24ba7c87a8ce2 +Signed-off-by: Kamil Dudka +--- + docs/cmdline-opts/cert.d | 7 ++++++ + docs/cmdline-opts/key.d | 7 ++++++ + lib/vtls/openssl.c | 38 ++++++++++++++++++++++++++++ + src/tool_getparam.c | 2 +- + src/tool_operate.c | 53 ++++++++++++++++++++++++++++++++++++++++ + tests/unit/unit1394.c | 3 +++ + 6 files changed, 109 insertions(+), 1 deletion(-) + +diff --git a/docs/cmdline-opts/cert.d b/docs/cmdline-opts/cert.d +index 0cd5d53..ae6fe2f 100644 +--- a/docs/cmdline-opts/cert.d ++++ b/docs/cmdline-opts/cert.d +@@ -23,6 +23,13 @@ nickname contains ":", it needs to be preceded by "\\" so that it is not + recognized as password delimiter. If the nickname contains "\\", it needs to + be escaped as "\\\\" so that it is not recognized as an escape character. + ++If curl is built against OpenSSL library, and the engine pkcs11 is available, ++then a PKCS#11 URI (RFC 7512) can be used to specify a certificate located in ++a PKCS#11 device. A string beginning with "pkcs11:" will be interpreted as a ++PKCS#11 URI. If a PKCS#11 URI is provided, then the --engine option will be set ++as "pkcs11" if none was provided and the --cert-type option will be set as ++"ENG" if none was provided. ++ + (iOS and macOS only) If curl is built against Secure Transport, then the + certificate string can either be the name of a certificate/private key in the + system or user keychain, or the path to a PKCS#12-encoded certificate and +diff --git a/docs/cmdline-opts/key.d b/docs/cmdline-opts/key.d +index fbf583a..4877b42 100644 +--- a/docs/cmdline-opts/key.d ++++ b/docs/cmdline-opts/key.d +@@ -7,4 +7,11 @@ Private key file name. Allows you to provide your private key in this separate + file. For SSH, if not specified, curl tries the following candidates in order: + '~/.ssh/id_rsa', '~/.ssh/id_dsa', './id_rsa', './id_dsa'. + ++If curl is built against OpenSSL library, and the engine pkcs11 is available, ++then a PKCS#11 URI (RFC 7512) can be used to specify a private key located in a ++PKCS#11 device. A string beginning with "pkcs11:" will be interpreted as a ++PKCS#11 URI. If a PKCS#11 URI is provided, then the --engine option will be set ++as "pkcs11" if none was provided and the --key-type option will be set as ++"ENG" if none was provided. ++ + If this option is used several times, the last one will be used. +diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c +index 8c1d5a8..82c3c86 100644 +--- a/lib/vtls/openssl.c ++++ b/lib/vtls/openssl.c +@@ -380,8 +380,25 @@ static int ssl_ui_writer(UI *ui, UI_STRING *uis) + } + return (UI_method_get_writer(UI_OpenSSL()))(ui, uis); + } ++ ++/* ++ * Check if a given string is a PKCS#11 URI ++ */ ++static bool is_pkcs11_uri(const char *string) ++{ ++ if(strncasecompare(string, "pkcs11:", 7)) { ++ return TRUE; ++ } ++ else { ++ return FALSE; ++ } ++} ++ + #endif + ++CURLcode Curl_ossl_set_engine(struct Curl_easy *data, ++ const char *engine); ++ + static + int cert_stuff(struct connectdata *conn, + SSL_CTX* ctx, +@@ -443,6 +460,16 @@ int cert_stuff(struct connectdata *conn, + case SSL_FILETYPE_ENGINE: + #if defined(HAVE_OPENSSL_ENGINE_H) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME) + { ++ /* Implicitly use pkcs11 engine if none was provided and the ++ * cert_file is a PKCS#11 URI */ ++ if(!data->state.engine) { ++ if(is_pkcs11_uri(cert_file)) { ++ if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) { ++ return 0; ++ } ++ } ++ } ++ + if(data->state.engine) { + const char *cmd_name = "LOAD_CERT_CTRL"; + struct { +@@ -614,6 +641,17 @@ int cert_stuff(struct connectdata *conn, + #ifdef HAVE_OPENSSL_ENGINE_H + { /* XXXX still needs some work */ + EVP_PKEY *priv_key = NULL; ++ ++ /* Implicitly use pkcs11 engine if none was provided and the ++ * key_file is a PKCS#11 URI */ ++ if(!data->state.engine) { ++ if(is_pkcs11_uri(key_file)) { ++ if(Curl_ossl_set_engine(data, "pkcs11") != CURLE_OK) { ++ return 0; ++ } ++ } ++ } ++ + if(data->state.engine) { + UI_METHOD *ui_method = + UI_create_method((char *)"curl user interface"); +diff --git a/src/tool_getparam.c b/src/tool_getparam.c +index b7ee519..7399757 100644 +--- a/src/tool_getparam.c ++++ b/src/tool_getparam.c +@@ -333,7 +333,7 @@ void parse_cert_parameter(const char *cert_parameter, + * looks like a RFC7512 PKCS#11 URI which can be used as-is. + * Also if cert_parameter contains no colon nor backslash, this + * means no passphrase was given and no characters escaped */ +- if(!strncmp(cert_parameter, "pkcs11:", 7) || ++ if(curl_strnequal(cert_parameter, "pkcs11:", 7) || + !strpbrk(cert_parameter, ":\\")) { + *certname = strdup(cert_parameter); + return; +diff --git a/src/tool_operate.c b/src/tool_operate.c +index 1e8d007..f041427 100644 +--- a/src/tool_operate.c ++++ b/src/tool_operate.c +@@ -127,6 +127,19 @@ static bool is_fatal_error(CURLcode code) + return FALSE; + } + ++/* ++ * Check if a given string is a PKCS#11 URI ++ */ ++static bool is_pkcs11_uri(const char *string) ++{ ++ if(curl_strnequal(string, "pkcs11:", 7)) { ++ return TRUE; ++ } ++ else { ++ return FALSE; ++ } ++} ++ + #ifdef __VMS + /* + * get_vms_file_size does what it takes to get the real size of the file +@@ -1136,6 +1149,46 @@ static CURLcode operate_do(struct GlobalConfig *global, + my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey); + + if(curlinfo->features & CURL_VERSION_SSL) { ++ /* Check if config->cert is a PKCS#11 URI and set the ++ * config->cert_type if necessary */ ++ if(config->cert) { ++ if(!config->cert_type) { ++ if(is_pkcs11_uri(config->cert)) { ++ config->cert_type = strdup("ENG"); ++ } ++ } ++ } ++ ++ /* Check if config->key is a PKCS#11 URI and set the ++ * config->key_type if necessary */ ++ if(config->key) { ++ if(!config->key_type) { ++ if(is_pkcs11_uri(config->key)) { ++ config->key_type = strdup("ENG"); ++ } ++ } ++ } ++ ++ /* Check if config->proxy_cert is a PKCS#11 URI and set the ++ * config->proxy_type if necessary */ ++ if(config->proxy_cert) { ++ if(!config->proxy_cert_type) { ++ if(is_pkcs11_uri(config->proxy_cert)) { ++ config->proxy_cert_type = strdup("ENG"); ++ } ++ } ++ } ++ ++ /* Check if config->proxy_key is a PKCS#11 URI and set the ++ * config->proxy_key_type if necessary */ ++ if(config->proxy_key) { ++ if(!config->proxy_key_type) { ++ if(is_pkcs11_uri(config->proxy_key)) { ++ config->proxy_key_type = strdup("ENG"); ++ } ++ } ++ } ++ + my_setopt_str(curl, CURLOPT_SSLCERT, config->cert); + my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert); + my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type); +diff --git a/tests/unit/unit1394.c b/tests/unit/unit1394.c +index 667991d..010f052 100644 +--- a/tests/unit/unit1394.c ++++ b/tests/unit/unit1394.c +@@ -56,6 +56,9 @@ UNITTEST_START + "foo:bar\\\\", "foo", "bar\\\\", + "foo:bar:", "foo", "bar:", + "foo\\::bar\\:", "foo:", "bar\\:", ++ "pkcs11:foobar", "pkcs11:foobar", NULL, ++ "PKCS11:foobar", "PKCS11:foobar", NULL, ++ "PkCs11:foobar", "PkCs11:foobar", NULL, + #ifdef WIN32 + "c:\\foo:bar:baz", "c:\\foo", "bar:baz", + "c:\\foo\\:bar:baz", "c:\\foo:bar", "baz", +-- +2.17.1 + diff --git a/0022-curl-7.55.1-CVE-2018-14618.patch b/0022-curl-7.55.1-CVE-2018-14618.patch new file mode 100644 index 0000000..6e4907e --- /dev/null +++ b/0022-curl-7.55.1-CVE-2018-14618.patch @@ -0,0 +1,144 @@ +From bde648303aea273a688e65a1caafdd94b7b0123e Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 4 Nov 2017 16:42:21 +0100 +Subject: [PATCH 1/3] ntlm: avoid malloc(0) for zero length passwords + +It triggers an assert() when built with memdebug since malloc(0) may +return NULL *or* a valid pointer. + +Detected by OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=4054 + +Assisted-by: Max Dymond +Closes #2054 + +Upstream-commit: 685ef130575cdcf63fe9547757d88a49a40ef281 +Signed-off-by: Kamil Dudka +--- + lib/curl_ntlm_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c +index eb44f97..1c7b7b0 100644 +--- a/lib/curl_ntlm_core.c ++++ b/lib/curl_ntlm_core.c +@@ -538,7 +538,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, + unsigned char *ntbuffer /* 21 bytes */) + { + size_t len = strlen(password); +- unsigned char *pw = malloc(len * 2); ++ unsigned char *pw = len ? malloc(len * 2) : strdup(""); + CURLcode result; + if(!pw) + return CURLE_OUT_OF_MEMORY; +-- +2.17.1 + + +From 2a23557fe8ab3316c5f961f79e50a03ab54cb07f Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 27 Nov 2017 10:40:31 +0100 +Subject: [PATCH 2/3] curl_ntlm_core.c: use the limits.h's SIZE_T_MAX if + provided + +Upstream-commit: 014887c50ab58bf35b1231dbfe11197fe41d59cc +Signed-off-by: Kamil Dudka +--- + lib/curl_ntlm_core.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c +index 1c7b7b0..9fc3e8d 100644 +--- a/lib/curl_ntlm_core.c ++++ b/lib/curl_ntlm_core.c +@@ -622,11 +622,14 @@ CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, + return CURLE_OK; + } + ++#ifndef SIZE_T_MAX ++/* some limits.h headers have this defined, some don't */ + #if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4) + #define SIZE_T_MAX 18446744073709551615U + #else + #define SIZE_T_MAX 4294967295U + #endif ++#endif + + /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode + * (uppercase UserName + Domain) as the data +-- +2.17.1 + + +From 405a7e855f1dfcc03d01e441cc53db1980c4454d Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 13 Aug 2018 10:35:52 +0200 +Subject: [PATCH 3/3] Curl_ntlm_core_mk_nt_hash: return error on too long + password + +... since it would cause an integer overflow if longer than (max size_t +/ 2). + +This is CVE-2018-14618 + +Bug: https://curl.haxx.se/docs/CVE-2018-14618.html +Closes #2756 +Reported-by: Zhaoyang Wu + +Upstream-commit: 57d299a499155d4b327e341c6024e293b0418243 +Signed-off-by: Kamil Dudka +--- + lib/curl_ntlm_core.c | 23 +++++++++++++---------- + 1 file changed, 13 insertions(+), 10 deletions(-) + +diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c +index 9fc3e8d..34d8b67 100644 +--- a/lib/curl_ntlm_core.c ++++ b/lib/curl_ntlm_core.c +@@ -124,6 +124,15 @@ + #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" + #define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) + ++#ifndef SIZE_T_MAX ++/* some limits.h headers have this defined, some don't */ ++#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4) ++#define SIZE_T_MAX 18446744073709551615U ++#else ++#define SIZE_T_MAX 4294967295U ++#endif ++#endif ++ + /* + * Turns a 56-bit key into being 64-bit wide. + */ +@@ -538,8 +547,11 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data, + unsigned char *ntbuffer /* 21 bytes */) + { + size_t len = strlen(password); +- unsigned char *pw = len ? malloc(len * 2) : strdup(""); ++ unsigned char *pw; + CURLcode result; ++ if(len > SIZE_T_MAX/2) /* avoid integer overflow */ ++ return CURLE_OUT_OF_MEMORY; ++ pw = len ? malloc(len * 2) : strdup(""); + if(!pw) + return CURLE_OUT_OF_MEMORY; + +@@ -622,15 +634,6 @@ CURLcode Curl_hmac_md5(const unsigned char *key, unsigned int keylen, + return CURLE_OK; + } + +-#ifndef SIZE_T_MAX +-/* some limits.h headers have this defined, some don't */ +-#if defined(SIZEOF_SIZE_T) && (SIZEOF_SIZE_T > 4) +-#define SIZE_T_MAX 18446744073709551615U +-#else +-#define SIZE_T_MAX 4294967295U +-#endif +-#endif +- + /* This creates the NTLMv2 hash by using NTLM hash as the key and Unicode + * (uppercase UserName + Domain) as the data + */ +-- +2.17.1 + diff --git a/curl.spec b/curl.spec index 23682db..50130d9 100644 --- a/curl.spec +++ b/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.55.1 -Release: 5%{?dist} +Release: 14%{?dist} License: MIT Group: Applications/Internet Source: https://curl.haxx.se/download/%{name}-%{version}.tar.xz @@ -12,6 +12,48 @@ Patch1: 0001-curl-7.55.1-zsh-completion.patch # http: Don't wait on CONNECT when there is no proxy (#1485702) Patch2: 0002-curl-7.55.1-proxy-connect.patch +# http2: handle GOAWAY properly (#1585797) +Patch4: 0004-curl-7.59.0-http2-GOAWAY.patch + +# fix out of bounds read in FTP PWD response parser (CVE-2017-1000254) +Patch5: 0005-curl-7.55.1-CVE-2017-1000254.patch + +# fix buffer overflow while processing IMAP FETCH response (CVE-2017-1000257) +Patch6: 0006-curl-7.55.1-CVE-2017-1000257.patch + +# fix FTP wildcard out of bounds read (CVE-2017-8817) +Patch7: 0007-curl-7.55.1-CVE-2017-8817.patch + +# fix NTLM buffer overflow via integer overflow (CVE-2017-8816) +Patch8: 0008-curl-7.55.1-CVE-2017-8816.patch + +# http: prevent custom Authorization headers in redirects (CVE-2018-1000007) +Patch9: 0009-curl-7.55.1-CVE-2018-1000007.patch + +# http2: fix incorrect trailer buffer size (CVE-2018-1000005) +Patch10: 0010-curl-7.55.1-CVE-2018-1000005.patch + +# fix RTSP RTP buffer over-read (CVE-2018-1000122) +Patch16: 0016-curl-7.55.1-CVE-2018-1000122.patch + +# fix LDAP NULL pointer dereference (CVE-2018-1000121) +Patch17: 0017-curl-7.55.1-CVE-2018-1000121.patch + +# fix FTP path trickery leads to NIL byte out of bounds write (CVE-2018-1000120) +Patch18: 0018-curl-7.55.1-CVE-2018-1000120.patch + +# fix RTSP bad headers buffer over-read (CVE-2018-1000301) +Patch19: 0019-curl-7.55.1-CVE-2018-1000301.patch + +# fix FTP shutdown response buffer overflow (CVE-2018-1000300) +Patch20: 0020-curl-7.55.1-CVE-2018-1000300.patch + +# ssl: set engine implicitly when a PKCS#11 URI is provided (#1219544) +Patch21: 0021-curl-7.55.1-pkcs11.patch + +# fix NTLM password overflow via integer overflow (CVE-2018-14618) +Patch22: 0022-curl-7.55.1-CVE-2018-14618.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.32.0-multilib.patch @@ -28,7 +70,7 @@ Provides: curl-full = %{version}-%{release} Provides: webclient URL: https://curl.haxx.se/ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(id -nu) -#BuildRequires: automake +BuildRequires: automake BuildRequires: groff BuildRequires: krb5-devel BuildRequires: libidn2-devel @@ -160,6 +202,20 @@ be installed. # upstream patches %patch1 -p1 %patch2 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 # Fedora patches %patch101 -p1 @@ -168,8 +224,8 @@ be installed. %patch104 -p1 # regenerate Makefile.in files -#aclocal -I m4 -#automake +aclocal -I m4 +automake # disable test 1112 (#565305) and test 1801 # @@ -314,6 +370,38 @@ rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la %{_libdir}/libcurl.so.[0-9].[0-9].[0-9].minimal %changelog +* Wed Sep 05 2018 Kamil Dudka - 7.55.1-14 +- fix NTLM password overflow via integer overflow (CVE-2018-14618) + +* Thu Aug 09 2018 Kamil Dudka - 7.55.1-13 +- ssl: set engine implicitly when a PKCS#11 URI is provided (#1219544) + +* Tue Jun 05 2018 Kamil Dudka - 7.55.1-12 +- http2: handle GOAWAY properly (#1585797) + +* Fri May 18 2018 Kamil Dudka - 7.55.1-11 +- fix FTP shutdown response buffer overflow (CVE-2018-1000300) +- fix RTSP bad headers buffer over-read (CVE-2018-1000301) + +* Wed Mar 14 2018 Kamil Dudka - 7.55.1-10 +- fix FTP path trickery leads to NIL byte out of bounds write (CVE-2018-1000120) +- fix LDAP NULL pointer dereference (CVE-2018-1000121) +- fix RTSP RTP buffer over-read (CVE-2018-1000122) + +* Wed Jan 24 2018 Kamil Dudka - 7.55.1-9 +- http2: fix incorrect trailer buffer size (CVE-2018-1000005) +- http: prevent custom Authorization headers in redirects (CVE-2018-1000007) + +* Thu Nov 30 2017 Kamil Dudka - 7.55.1-8 +- fix NTLM buffer overflow via integer overflow (CVE-2017-8816) +- fix FTP wildcard out of bounds read (CVE-2017-8817) + +* Mon Oct 23 2017 Kamil Dudka - 7.55.1-7 +- fix buffer overflow while processing IMAP FETCH response (CVE-2017-1000257) + +* Wed Oct 04 2017 Kamil Dudka - 7.55.1-6 +- fix out of bounds read in FTP PWD response parser (CVE-2017-1000254) + * Mon Aug 28 2017 Kamil Dudka - 7.55.1-5 - apply the patch for the previous commit and fix its name (#1485702)