diff --git a/SOURCES/0018-curl-7.29.0-517b06d6.patch b/SOURCES/0018-curl-7.29.0-517b06d6.patch deleted file mode 100644 index b56875e..0000000 --- a/SOURCES/0018-curl-7.29.0-517b06d6.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 46e85fee025964dd9a8ce2d615bc5f8ece530519 Mon Sep 17 00:00:00 2001 -From: Steve Holme -Date: Thu, 20 Feb 2014 23:51:36 +0000 -Subject: [PATCH] url: Fixed connection re-use when using different log-in credentials - -In addition to FTP, other connection based protocols such as IMAP, POP3, -SMTP, SCP, SFTP and LDAP require a new connection when different log-in -credentials are specified. Fixed the detection logic to include these -other protocols. - -Bug: http://curl.haxx.se/docs/adv_20140326A.html - -[upstream commit 517b06d657aceb11a234b05cc891170c367ab80d] - -Signed-off-by: Kamil Dudka ---- - lib/http.c | 2 +- - lib/url.c | 6 +++--- - lib/urldata.h | 2 ++ - 3 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/lib/http.c b/lib/http.c -index f4b7a48..c78036b 100644 ---- a/lib/http.c -+++ b/lib/http.c -@@ -142,7 +142,7 @@ const struct Curl_handler Curl_handler_https = { - ZERO_NULL, /* readwrite */ - PORT_HTTPS, /* defport */ - CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */ -- PROTOPT_SSL /* flags */ -+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST /* flags */ - }; - #endif - -diff --git a/lib/url.c b/lib/url.c -index 9690dfa..0174ff4 100644 ---- a/lib/url.c -+++ b/lib/url.c -@@ -2961,10 +2961,10 @@ ConnectionExists(struct SessionHandle *data, - continue; - } - } -- if((needle->handler->protocol & CURLPROTO_FTP) || -+ if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) || - ((needle->handler->protocol & CURLPROTO_HTTP) && wantNTLM)) { -- /* This is FTP or HTTP+NTLM, verify that we're using the same name -- and password as well */ -+ /* This protocol requires credentials per connection or is HTTP+NTLM, -+ so verify that we're using the same name and password as well */ - if(!strequal(needle->user, check->user) || - !strequal(needle->passwd, check->passwd)) { - /* one of them was different */ -diff --git a/lib/urldata.h b/lib/urldata.h -index d597c67..cbf4102 100644 ---- a/lib/urldata.h -+++ b/lib/urldata.h -@@ -755,6 +755,8 @@ struct Curl_handler { - gets a default */ - #define PROTOPT_NOURLQUERY (1<<6) /* protocol can't handle - url query strings (?foo=bar) ! */ -+#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login creditials per request -+ as opposed to per connection */ - - - /* return the count of bytes sent, or -1 on error */ --- -1.7.1 - diff --git a/SOURCES/0019-curl-7.29.0-517b06d6.patch b/SOURCES/0019-curl-7.29.0-517b06d6.patch new file mode 100644 index 0000000..b56875e --- /dev/null +++ b/SOURCES/0019-curl-7.29.0-517b06d6.patch @@ -0,0 +1,68 @@ +From 46e85fee025964dd9a8ce2d615bc5f8ece530519 Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Thu, 20 Feb 2014 23:51:36 +0000 +Subject: [PATCH] url: Fixed connection re-use when using different log-in credentials + +In addition to FTP, other connection based protocols such as IMAP, POP3, +SMTP, SCP, SFTP and LDAP require a new connection when different log-in +credentials are specified. Fixed the detection logic to include these +other protocols. + +Bug: http://curl.haxx.se/docs/adv_20140326A.html + +[upstream commit 517b06d657aceb11a234b05cc891170c367ab80d] + +Signed-off-by: Kamil Dudka +--- + lib/http.c | 2 +- + lib/url.c | 6 +++--- + lib/urldata.h | 2 ++ + 3 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/lib/http.c b/lib/http.c +index f4b7a48..c78036b 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -142,7 +142,7 @@ const struct Curl_handler Curl_handler_https = { + ZERO_NULL, /* readwrite */ + PORT_HTTPS, /* defport */ + CURLPROTO_HTTP | CURLPROTO_HTTPS, /* protocol */ +- PROTOPT_SSL /* flags */ ++ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST /* flags */ + }; + #endif + +diff --git a/lib/url.c b/lib/url.c +index 9690dfa..0174ff4 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -2961,10 +2961,10 @@ ConnectionExists(struct SessionHandle *data, + continue; + } + } +- if((needle->handler->protocol & CURLPROTO_FTP) || ++ if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) || + ((needle->handler->protocol & CURLPROTO_HTTP) && wantNTLM)) { +- /* This is FTP or HTTP+NTLM, verify that we're using the same name +- and password as well */ ++ /* This protocol requires credentials per connection or is HTTP+NTLM, ++ so verify that we're using the same name and password as well */ + if(!strequal(needle->user, check->user) || + !strequal(needle->passwd, check->passwd)) { + /* one of them was different */ +diff --git a/lib/urldata.h b/lib/urldata.h +index d597c67..cbf4102 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -755,6 +755,8 @@ struct Curl_handler { + gets a default */ + #define PROTOPT_NOURLQUERY (1<<6) /* protocol can't handle + url query strings (?foo=bar) ! */ ++#define PROTOPT_CREDSPERREQUEST (1<<7) /* requires login creditials per request ++ as opposed to per connection */ + + + /* return the count of bytes sent, or -1 on error */ +-- +1.7.1 + diff --git a/SOURCES/0020-curl-7.29.0-d529f388.patch b/SOURCES/0020-curl-7.29.0-d529f388.patch new file mode 100644 index 0000000..5776c6d --- /dev/null +++ b/SOURCES/0020-curl-7.29.0-d529f388.patch @@ -0,0 +1,40 @@ +From 4274decb62daca78c9d43a025fc08f8d6fd3a341 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sun, 14 Jul 2013 17:33:24 +0200 +Subject: [PATCH] curl_easy_perform: gradually increase the delay time + +Instead of going 50,100,150 etc millisecond delay time when nothing has +been found to do or wait for, we now start lower and double each loop as +in 4,8,16,32 etc. + +This lowers the minimum wait without sacrifizing the longer wait too +much with unnecessary CPU cycles burnt. + +Bug: http://curl.haxx.se/mail/lib-2013-07/0103.html +Reported-by: Andreas Malzahn + +[upstream commit d529f3882b9bca2c3eb32295dd6b2609d0c9b51f] + +Signed-off-by: Kamil Dudka +--- + lib/easy.c | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/lib/easy.c b/lib/easy.c +index a7051dd..13801b2 100644 +--- a/lib/easy.c ++++ b/lib/easy.c +@@ -465,9 +465,7 @@ CURLcode curl_easy_perform(CURL *easy) + if(curlx_tvdiff(after, before) <= 10) { + without_fds++; + if(without_fds > 2) { +- int sleep_ms = without_fds * 50; +- if(sleep_ms > 1000) +- sleep_ms = 1000; ++ int sleep_ms = without_fds < 10 ? (1 << (without_fds-1)): 1000; + Curl_wait_ms(sleep_ms); + } + } +-- +1.9.3 + diff --git a/SOURCES/0021-curl-7.29.0-67061e3f.patch b/SOURCES/0021-curl-7.29.0-67061e3f.patch new file mode 100644 index 0000000..ad6e8cf --- /dev/null +++ b/SOURCES/0021-curl-7.29.0-67061e3f.patch @@ -0,0 +1,153 @@ +From 6c5bb879f09c490ad9aebf50670cbe546d0aba4a Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 7 Mar 2014 13:02:03 +0100 +Subject: [PATCH 1/3] nss: do not enable AES cipher-suites by default + +... but allow them to be enabled/disabled explicitly. The default +policy should be maintained at the NSS level. + +Upstream-commit: b4f6cd46eb1b5a98573e0c0e619dc71646affdc8 +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 27 ++++----------------------- + 1 file changed, 4 insertions(+), 23 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index abc8a91..289c55b 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -122,6 +122,10 @@ static const cipher_s cipherlist[] = { + {"rsa_des_56_sha", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA}, + {"rsa_rc4_56_sha", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA}, + /* AES ciphers. */ ++ {"dhe_dss_aes_128_cbc_sha", TLS_DHE_DSS_WITH_AES_128_CBC_SHA}, ++ {"dhe_dss_aes_256_cbc_sha", TLS_DHE_DSS_WITH_AES_256_CBC_SHA}, ++ {"dhe_rsa_aes_128_cbc_sha", TLS_DHE_RSA_WITH_AES_128_CBC_SHA}, ++ {"dhe_rsa_aes_256_cbc_sha", TLS_DHE_RSA_WITH_AES_256_CBC_SHA}, + {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA}, + {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA}, + /* ECC ciphers. */ +@@ -152,18 +156,6 @@ static const cipher_s cipherlist[] = { + {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA}, + }; + +-/* following ciphers are new in NSS 3.4 and not enabled by default, therefore +- they are enabled explicitly */ +-static const int enable_ciphers_by_default[] = { +- TLS_DHE_DSS_WITH_AES_128_CBC_SHA, +- TLS_DHE_DSS_WITH_AES_256_CBC_SHA, +- TLS_DHE_RSA_WITH_AES_128_CBC_SHA, +- TLS_DHE_RSA_WITH_AES_256_CBC_SHA, +- TLS_RSA_WITH_AES_128_CBC_SHA, +- TLS_RSA_WITH_AES_256_CBC_SHA, +- SSL_NULL_WITH_NULL_NULL +-}; +- + static const char* pem_library = "libnsspem.so"; + SECMODModule* mod = NULL; + +@@ -1214,7 +1206,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CURLcode curlerr; +- const int *cipher_to_enable; + PRSocketOptionData sock_opt; + long time_left; + PRUint32 timeout; +@@ -1304,16 +1295,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + /* reset the flag to avoid an infinite loop */ + data->state.ssl_connect_retry = FALSE; + +- /* enable all ciphers from enable_ciphers_by_default */ +- cipher_to_enable = enable_ciphers_by_default; +- while(SSL_NULL_WITH_NULL_NULL != *cipher_to_enable) { +- if(SSL_CipherPrefSet(model, *cipher_to_enable, PR_TRUE) != SECSuccess) { +- curlerr = CURLE_SSL_CIPHER; +- goto error; +- } +- cipher_to_enable++; +- } +- + if(data->set.ssl.cipher_list) { + if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) { + curlerr = CURLE_SSL_CIPHER; +-- +2.1.0 + + +From 0dac41d2469fe2990197912f4e2d58e1de6957e6 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 7 Mar 2014 13:10:54 +0100 +Subject: [PATCH 2/3] nss: allow to enable/disable new HMAC-SHA256 + cipher-suites + +... if built against a new enough version of NSS + +Upstream-commit: c864d81289297b04dbbca14e3c5307ef15e6f258 +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/lib/nss.c b/lib/nss.c +index 289c55b..ea0d4ef 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -154,6 +154,16 @@ static const cipher_s cipherlist[] = { + {"ecdh_anon_3des_sha", TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA}, + {"ecdh_anon_aes_128_sha", TLS_ECDH_anon_WITH_AES_128_CBC_SHA}, + {"ecdh_anon_aes_256_sha", TLS_ECDH_anon_WITH_AES_256_CBC_SHA}, ++#ifdef TLS_RSA_WITH_NULL_SHA256 ++ /* new HMAC-SHA256 cipher suites specified in RFC */ ++ {"rsa_null_sha_256", TLS_RSA_WITH_NULL_SHA256}, ++ {"rsa_aes_128_cbc_sha_256", TLS_RSA_WITH_AES_128_CBC_SHA256}, ++ {"rsa_aes_256_cbc_sha_256", TLS_RSA_WITH_AES_256_CBC_SHA256}, ++ {"dhe_rsa_aes_128_cbc_sha_256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256}, ++ {"dhe_rsa_aes_256_cbc_sha_256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256}, ++ {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}, ++ {"ecdhe_rsa_aes_128_cbc_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256}, ++#endif + }; + + static const char* pem_library = "libnsspem.so"; +-- +2.1.0 + + +From f9c89d4cf767a7e2ae39ae668ec30a71513a3d98 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 7 Mar 2014 13:14:08 +0100 +Subject: [PATCH 3/3] nss: allow to enable/disable new AES GCM cipher-suites + +... if built against a new enough version of NSS + +Upstream-commit: 67061e3f4ec1c2f3b4bb02bbe2d91ccdeb147c60 +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/lib/nss.c b/lib/nss.c +index ea0d4ef..1381dc4 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -164,6 +164,16 @@ static const cipher_s cipherlist[] = { + {"ecdhe_ecdsa_aes_128_cbc_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}, + {"ecdhe_rsa_aes_128_cbc_sha_256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256}, + #endif ++#ifdef TLS_RSA_WITH_AES_128_GCM_SHA256 ++ /* AES GCM cipher suites in RFC 5288 and RFC 5289 */ ++ {"rsa_aes_128_gcm_sha_256", TLS_RSA_WITH_AES_128_GCM_SHA256}, ++ {"dhe_rsa_aes_128_gcm_sha_256", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256}, ++ {"dhe_dss_aes_128_gcm_sha_256", TLS_DHE_DSS_WITH_AES_128_GCM_SHA256}, ++ {"ecdhe_ecdsa_aes_128_gcm_sha_256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, ++ {"ecdh_ecdsa_aes_128_gcm_sha_256", TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256}, ++ {"ecdhe_rsa_aes_128_gcm_sha_256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, ++ {"ecdh_rsa_aes_128_gcm_sha_256", TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256}, ++#endif + }; + + static const char* pem_library = "libnsspem.so"; +-- +2.1.0 + diff --git a/SOURCES/0022-curl-7.29.0-24c3cdce.patch b/SOURCES/0022-curl-7.29.0-24c3cdce.patch new file mode 100644 index 0000000..5dac548 --- /dev/null +++ b/SOURCES/0022-curl-7.29.0-24c3cdce.patch @@ -0,0 +1,142 @@ +From ca7b1cd659eb0eb0ef355e3e122742abcea73287 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 2 Jul 2014 16:34:48 +0200 +Subject: [PATCH 1/2] tool: call PR_Cleanup() on exit if NSPR is used + +This prevents valgrind from reporting possibly lost memory that NSPR +uses for file descriptor cache and other globally allocated internal +data structures. + +Upstream-commit: 24c3cdce88f39731506c287cb276e8bf4a1ce393 +Signed-off-by: Kamil Dudka +--- + src/tool_main.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/tool_main.c b/src/tool_main.c +index 95e9cc7..6a1ed6c 100644 +--- a/src/tool_main.c ++++ b/src/tool_main.c +@@ -27,6 +27,10 @@ + #include + #endif + ++#ifdef USE_NSS ++#include ++#endif ++ + #define ENABLE_CURLX_PRINTF + /* use our own printf() functions */ + #include "curlx.h" +@@ -104,6 +108,12 @@ int main(int argc, char *argv[]) + tool_pressanykey(); + #endif + ++#ifdef USE_NSS ++ if(PR_Initialized()) ++ /* prevent valgrind from reporting possibly lost memory (fd cache, ...) */ ++ PR_Cleanup(); ++#endif ++ + free_config_fields(&config); + + #ifdef __NOVELL_LIBC__ +-- +2.1.0 + + +From 295471f8122cf6522c36f8e3588e5b4d15a691ea Mon Sep 17 00:00:00 2001 +From: Alessandro Ghedini +Date: Thu, 17 Jul 2014 14:37:28 +0200 +Subject: [PATCH 2/2] build: link curl to NSS libraries when NSS support is + enabled + +This fixes a build failure on Debian caused by commit +24c3cdce88f39731506c287cb276e8bf4a1ce393. + +Bug: http://curl.haxx.se/mail/lib-2014-07/0209.html + +Upstream-commit: c6e7cbb94e669b85d3eb8e015ec51d0072112133 +Signed-off-by: Kamil Dudka +--- + configure | 5 ++++- + configure.ac | 4 ++++ + src/Makefile.am | 2 +- + src/Makefile.in | 3 ++- + 4 files changed, 11 insertions(+), 3 deletions(-) + +diff --git a/configure b/configure +index 8741e21..c5d1817 100755 +--- a/configure ++++ b/configure +@@ -913,7 +913,7 @@ LIBMETALINK_LIBS + CURL_CA_BUNDLE + SSL_ENABLED + USE_AXTLS +-HAVE_NSS_INITCONTEXT ++NSS_LIBS + USE_NSS + USE_CYASSL + USE_POLARSSL +@@ -23697,6 +23697,9 @@ fi + { $as_echo "$as_me:${as_lineno-$LINENO}: detected NSS version $version" >&5 + $as_echo "$as_me: detected NSS version $version" >&6;} + ++ NSS_LIBS=$addlib ++ ++ + if test "x$cross_compiling" != "xyes"; then + LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$nssprefix/lib$libsuff" + export LD_LIBRARY_PATH +diff --git a/configure.ac b/configure.ac +index 70ef0b7..60a6b58 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2211,6 +2211,10 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then + if test "x$USE_NSS" = "xyes"; then + AC_MSG_NOTICE([detected NSS version $version]) + ++ dnl needed when linking the curl tool without USE_EXPLICIT_LIB_DEPS ++ NSS_LIBS=$addlib ++ AC_SUBST([NSS_LIBS]) ++ + dnl when shared libs were found in a path that the run-time + dnl linker doesn't search through, we need to add it to + dnl LD_LIBRARY_PATH to prevent further configure tests to fail +diff --git a/src/Makefile.am b/src/Makefile.am +index af5a488..6863078 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -60,7 +60,7 @@ LIBS = $(BLANK_AT_MAKETIME) + if USE_EXPLICIT_LIB_DEPS + curl_LDADD = $(top_builddir)/lib/libcurl.la @LIBMETALINK_LIBS@ @LIBCURL_LIBS@ + else +-curl_LDADD = $(top_builddir)/lib/libcurl.la @LIBMETALINK_LIBS@ @ZLIB_LIBS@ @CURL_NETWORK_AND_TIME_LIBS@ ++curl_LDADD = $(top_builddir)/lib/libcurl.la @LIBMETALINK_LIBS@ @NSS_LIBS@ @ZLIB_LIBS@ @CURL_NETWORK_AND_TIME_LIBS@ + endif + + curl_LDFLAGS = @LIBMETALINK_LDFLAGS@ +diff --git a/src/Makefile.in b/src/Makefile.in +index 41fb549..1b578c2 100644 +--- a/src/Makefile.in ++++ b/src/Makefile.in +@@ -231,6 +231,7 @@ NMEDIT = @NMEDIT@ + # Use the C locale to ensure that only ASCII characters appear in the + # embedded text. + NROFF = env LC_ALL=C @NROFF@ @MANOPT@ # figured out by the configure script ++NSS_LIBS = @NSS_LIBS@ + OBJDUMP = @OBJDUMP@ + OBJEXT = @OBJEXT@ + OTOOL = @OTOOL@ +@@ -463,7 +464,7 @@ CURL_HFILES = \ + tool_xattr.h + + curl_SOURCES = $(CURL_CFILES) $(CURLX_ONES) $(CURL_HFILES) +-@USE_EXPLICIT_LIB_DEPS_FALSE@curl_LDADD = $(top_builddir)/lib/libcurl.la @LIBMETALINK_LIBS@ @ZLIB_LIBS@ @CURL_NETWORK_AND_TIME_LIBS@ ++@USE_EXPLICIT_LIB_DEPS_FALSE@curl_LDADD = $(top_builddir)/lib/libcurl.la @LIBMETALINK_LIBS@ @NSS_LIBS@ @ZLIB_LIBS@ @CURL_NETWORK_AND_TIME_LIBS@ + @USE_EXPLICIT_LIB_DEPS_TRUE@curl_LDADD = $(top_builddir)/lib/libcurl.la @LIBMETALINK_LIBS@ @LIBCURL_LIBS@ + curl_LDFLAGS = @LIBMETALINK_LDFLAGS@ + curl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBMETALINK_CPPFLAGS) +-- +2.1.0 + diff --git a/SOURCES/0023-curl-7.29.0-8868a226.patch b/SOURCES/0023-curl-7.29.0-8868a226.patch new file mode 100644 index 0000000..e4e3ab8 --- /dev/null +++ b/SOURCES/0023-curl-7.29.0-8868a226.patch @@ -0,0 +1,591 @@ +From 355f7594877a62f9aa657e8a72d3f92b3c887d73 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Thu, 17 Apr 2014 13:12:59 +0200 +Subject: [PATCH 1/4] nss: split Curl_nss_connect() into 4 functions + +Upstream-commit: a43bba3a34ed8912c4ca10f213590d1998ba0d29 +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 134 +++++++++++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 94 insertions(+), 40 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 1381dc4..4d57a24 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1216,9 +1216,62 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver, + return CURLE_SSL_CONNECT_ERROR; + } + +-CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) ++static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, ++ struct SessionHandle *data, ++ CURLcode curlerr) + { ++ SSLVersionRange sslver; + PRErrorCode err = 0; ++ ++ /* reset the flag to avoid an infinite loop */ ++ data->state.ssl_connect_retry = FALSE; ++ ++ if(is_nss_error(curlerr)) { ++ /* read NSPR error code */ ++ err = PR_GetError(); ++ if(is_cc_error(err)) ++ curlerr = CURLE_SSL_CERTPROBLEM; ++ ++ /* print the error number and error string */ ++ infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err)); ++ ++ /* print a human-readable message describing the error if available */ ++ nss_print_error_message(data, err); ++ } ++ ++ /* cleanup on connection failure */ ++ Curl_llist_destroy(connssl->obj_list, NULL); ++ connssl->obj_list = NULL; ++ ++ if((SSL_VersionRangeGet(connssl->handle, &sslver) == SECSuccess) ++ && (sslver.min == SSL_LIBRARY_VERSION_3_0) ++ && (sslver.max == SSL_LIBRARY_VERSION_TLS_1_0) ++ && isTLSIntoleranceError(err)) { ++ /* schedule reconnect through Curl_retry_request() */ ++ data->state.ssl_connect_retry = TRUE; ++ infof(data, "Error in TLS handshake, trying SSLv3...\n"); ++ return CURLE_OK; ++ } ++ ++ return curlerr; ++} ++ ++/* Switch the SSL socket into non-blocking mode. */ ++static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl, ++ struct SessionHandle *data) ++{ ++ static PRSocketOptionData sock_opt; ++ sock_opt.option = PR_SockOpt_Nonblocking; ++ sock_opt.value.non_blocking = PR_TRUE; ++ ++ if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS) ++ return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR); ++ ++ return CURLE_OK; ++} ++ ++static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) ++{ + PRFileDesc *model = NULL; + PRBool ssl_no_cache; + PRBool ssl_cbc_random_iv; +@@ -1226,9 +1279,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + curl_socket_t sockfd = conn->sock[sockindex]; + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + CURLcode curlerr; +- PRSocketOptionData sock_opt; +- long time_left; +- PRUint32 timeout; + + SSLVersionRange sslver = { + SSL_LIBRARY_VERSION_3_0, /* min */ +@@ -1402,16 +1452,32 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + + SSL_SetURL(connssl->handle, conn->host.name); + ++ return CURLE_OK; ++ ++error: ++ if(model) ++ PR_Close(model); ++ ++ return nss_fail_connect(connssl, data, curlerr); ++} ++ ++static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) ++{ ++ struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ++ struct SessionHandle *data = conn->data; ++ CURLcode curlerr = CURLE_SSL_CONNECT_ERROR; ++ PRUint32 timeout; ++ + /* check timeout situation */ +- time_left = Curl_timeleft(data, NULL, TRUE); ++ const long time_left = Curl_timeleft(data, NULL, TRUE); + if(time_left < 0L) { + failf(data, "timed out before SSL handshake"); + curlerr = CURLE_OPERATION_TIMEDOUT; + goto error; + } +- timeout = PR_MillisecondsToInterval((PRUint32) time_left); + + /* Force the handshake now */ ++ timeout = PR_MillisecondsToInterval((PRUint32) time_left); + if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) { + if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) + curlerr = CURLE_PEER_FAILED_VERIFICATION; +@@ -1420,12 +1486,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + goto error; + } + +- /* switch the SSL socket into non-blocking mode */ +- sock_opt.option = PR_SockOpt_Nonblocking; +- sock_opt.value.non_blocking = PR_TRUE; +- if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS) +- goto error; +- + connssl->state = ssl_connection_complete; + conn->recv[sockindex] = nss_recv; + conn->send[sockindex] = nss_send; +@@ -1453,40 +1513,34 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + + return CURLE_OK; + +- error: +- /* reset the flag to avoid an infinite loop */ +- data->state.ssl_connect_retry = FALSE; ++error: ++ return nss_fail_connect(connssl, data, curlerr); ++} + +- if(is_nss_error(curlerr)) { +- /* read NSPR error code */ +- err = PR_GetError(); +- if(is_cc_error(err)) +- curlerr = CURLE_SSL_CERTPROBLEM; ++CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) ++{ ++ struct ssl_connect_data *connssl = &conn->ssl[sockindex]; ++ struct SessionHandle *data = conn->data; ++ CURLcode rv; + +- /* print the error number and error string */ +- infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err)); ++ rv = nss_setup_connect(conn, sockindex); ++ if(rv) ++ return rv; + +- /* print a human-readable message describing the error if available */ +- nss_print_error_message(data, err); ++ rv = nss_do_connect(conn, sockindex); ++ switch(rv) { ++ case CURLE_OK: ++ break; ++ default: ++ return rv; + } + +- if(model) +- PR_Close(model); +- +- /* cleanup on connection failure */ +- Curl_llist_destroy(connssl->obj_list, NULL); +- connssl->obj_list = NULL; +- +- if((sslver.min == SSL_LIBRARY_VERSION_3_0) +- && (sslver.max == SSL_LIBRARY_VERSION_TLS_1_0) +- && isTLSIntoleranceError(err)) { +- /* schedule reconnect through Curl_retry_request() */ +- data->state.ssl_connect_retry = TRUE; +- infof(data, "Error in TLS handshake, trying SSLv3...\n"); +- return CURLE_OK; +- } ++ /* switch the SSL socket into non-blocking mode */ ++ rv = nss_set_nonblock(connssl, data); ++ if(rv) ++ return rv; + +- return curlerr; ++ return CURLE_OK; + } + + static ssize_t nss_send(struct connectdata *conn, /* connection data */ +-- +2.1.0 + + +From b5132ce96009510656e5f719c8805647c246685b Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Thu, 17 Apr 2014 13:27:39 +0200 +Subject: [PATCH 2/4] nss: implement non-blocking SSL handshake + +Upstream-commit: 8868a226cdad66a9a07d6e3f168884817592a1df +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++--------- + lib/nssg.h | 1 + + lib/urldata.h | 1 + + 3 files changed, 50 insertions(+), 9 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 4d57a24..5be1058 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1479,7 +1479,10 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) + /* Force the handshake now */ + timeout = PR_MillisecondsToInterval((PRUint32) time_left); + if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) { +- if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) ++ if(PR_GetError() == PR_WOULD_BLOCK_ERROR) ++ /* TODO: propagate the blocking direction from the NSPR layer */ ++ return CURLE_AGAIN; ++ else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) + curlerr = CURLE_PEER_FAILED_VERIFICATION; + else if(conn->data->set.ssl.certverifyresult!=0) + curlerr = CURLE_SSL_CACERT; +@@ -1517,32 +1520,68 @@ error: + return nss_fail_connect(connssl, data, curlerr); + } + +-CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) ++static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, ++ bool *done) + { + struct ssl_connect_data *connssl = &conn->ssl[sockindex]; + struct SessionHandle *data = conn->data; ++ const bool blocking = (done == NULL); + CURLcode rv; + +- rv = nss_setup_connect(conn, sockindex); +- if(rv) +- return rv; ++ if(connssl->connecting_state == ssl_connect_1) { ++ rv = nss_setup_connect(conn, sockindex); ++ if(rv) ++ /* we do not expect CURLE_AGAIN from nss_setup_connect() */ ++ return rv; ++ ++ if(!blocking) { ++ /* in non-blocking mode, set NSS non-blocking mode before handshake */ ++ rv = nss_set_nonblock(connssl, data); ++ if(rv) ++ return rv; ++ } ++ ++ connssl->connecting_state = ssl_connect_2; ++ } + + rv = nss_do_connect(conn, sockindex); + switch(rv) { + case CURLE_OK: + break; ++ case CURLE_AGAIN: ++ if(!blocking) ++ /* CURLE_AGAIN in non-blocking mode is not an error */ ++ return CURLE_OK; ++ /* fall through */ + default: + return rv; + } + +- /* switch the SSL socket into non-blocking mode */ +- rv = nss_set_nonblock(connssl, data); +- if(rv) +- return rv; ++ if(blocking) { ++ /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */ ++ rv = nss_set_nonblock(connssl, data); ++ if(rv) ++ return rv; ++ } ++ else ++ /* signal completed SSL handshake */ ++ *done = TRUE; + ++ connssl->connecting_state = ssl_connect_done; + return CURLE_OK; + } + ++CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) ++{ ++ return nss_connect_common(conn, sockindex, /* blocking */ NULL); ++} ++ ++CURLcode Curl_nss_connect_nonblocking(struct connectdata *conn, ++ int sockindex, bool *done) ++{ ++ return nss_connect_common(conn, sockindex, done); ++} ++ + static ssize_t nss_send(struct connectdata *conn, /* connection data */ + int sockindex, /* socketindex */ + const void *mem, /* send this data */ +diff --git a/lib/nssg.h b/lib/nssg.h +index a881a9a..6d9aea6 100644 +--- a/lib/nssg.h ++++ b/lib/nssg.h +@@ -64,6 +64,7 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */ + #define curlssl_init Curl_nss_init + #define curlssl_cleanup Curl_nss_cleanup + #define curlssl_connect Curl_nss_connect ++#define curlssl_connect_nonblocking Curl_nss_connect_nonblocking + + /* NSS has its own session ID cache */ + #define curlssl_session_free(x) Curl_nop_stmt +diff --git a/lib/urldata.h b/lib/urldata.h +index e5d85ff..c91bcff 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -303,6 +303,7 @@ struct ssl_connect_data { + struct SessionHandle *data; + struct curl_llist *obj_list; + PK11GenericObject *obj_clicert; ++ ssl_connect_state connecting_state; + #endif /* USE_NSS */ + #ifdef USE_QSOSSL + SSLHandle *handle; +-- +2.1.0 + + +From 2f1f1b1ca2d9c60c5fca5d73303ae2ec4c3d94b2 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 23 Apr 2014 15:37:26 +0200 +Subject: [PATCH 3/4] nss: propagate blocking direction from NSPR I/O + +... during the non-blocking SSL handshake + +Upstream-commit: 9c941e92c4bd3d2a5dbe243f7517b6a6029afc6e +Signed-off-by: Kamil Dudka +--- + lib/http.c | 2 +- + lib/nss.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- + 2 files changed, 104 insertions(+), 6 deletions(-) + +diff --git a/lib/http.c b/lib/http.c +index d1b0405..c007226 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1351,7 +1351,7 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done) + #endif + + #if defined(USE_SSLEAY) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \ +- defined(USE_DARWINSSL) ++ defined(USE_DARWINSSL) || defined(USE_NSS) + /* This function is for OpenSSL, GnuTLS, darwinssl, and schannel only. + It should be made to query the generic SSL layer instead. */ + static int https_getsock(struct connectdata *conn, +diff --git a/lib/nss.c b/lib/nss.c +index 5be1058..dadeb58 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -179,6 +179,10 @@ static const cipher_s cipherlist[] = { + static const char* pem_library = "libnsspem.so"; + SECMODModule* mod = NULL; + ++/* NSPR I/O layer we use to detect blocking direction during SSL handshake */ ++static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER; ++static PRIOMethods nspr_io_methods; ++ + static const char* nss_error_to_name(PRErrorCode code) + { + const char *name = PR_ErrorToName(code); +@@ -861,6 +865,60 @@ isTLSIntoleranceError(PRInt32 err) + } + } + ++/* update blocking direction in case of PR_WOULD_BLOCK_ERROR */ ++static void nss_update_connecting_state(ssl_connect_state state, void *secret) ++{ ++ struct ssl_connect_data *connssl = (struct ssl_connect_data *)secret; ++ if(PR_GetError() != PR_WOULD_BLOCK_ERROR) ++ /* an unrelated error is passing by */ ++ return; ++ ++ switch(connssl->connecting_state) { ++ case ssl_connect_2: ++ case ssl_connect_2_reading: ++ case ssl_connect_2_writing: ++ break; ++ default: ++ /* we are not called from an SSL handshake */ ++ return; ++ } ++ ++ /* update the state accordingly */ ++ connssl->connecting_state = state; ++} ++ ++/* recv() wrapper we use to detect blocking direction during SSL handshake */ ++static PRInt32 nspr_io_recv(PRFileDesc *fd, void *buf, PRInt32 amount, ++ PRIntn flags, PRIntervalTime timeout) ++{ ++ const PRRecvFN recv_fn = fd->lower->methods->recv; ++ const PRInt32 rv = recv_fn(fd->lower, buf, amount, flags, timeout); ++ if(rv < 0) ++ /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */ ++ nss_update_connecting_state(ssl_connect_2_reading, fd->secret); ++ return rv; ++} ++ ++/* send() wrapper we use to detect blocking direction during SSL handshake */ ++static PRInt32 nspr_io_send(PRFileDesc *fd, const void *buf, PRInt32 amount, ++ PRIntn flags, PRIntervalTime timeout) ++{ ++ const PRSendFN send_fn = fd->lower->methods->send; ++ const PRInt32 rv = send_fn(fd->lower, buf, amount, flags, timeout); ++ if(rv < 0) ++ /* check for PR_WOULD_BLOCK_ERROR and update blocking direction */ ++ nss_update_connecting_state(ssl_connect_2_writing, fd->secret); ++ return rv; ++} ++ ++/* close() wrapper to avoid assertion failure due to fd->secret != NULL */ ++static PRStatus nspr_io_close(PRFileDesc *fd) ++{ ++ const PRCloseFN close_fn = PR_GetDefaultIOMethods()->close; ++ fd->secret = NULL; ++ return close_fn(fd); ++} ++ + static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) + { + NSSInitParameters initparams; +@@ -925,6 +983,21 @@ static CURLcode nss_init(struct SessionHandle *data) + } + } + ++ if(nspr_io_identity == PR_INVALID_IO_LAYER) { ++ /* allocate an identity for our own NSPR I/O layer */ ++ nspr_io_identity = PR_GetUniqueIdentity("libcurl"); ++ if(nspr_io_identity == PR_INVALID_IO_LAYER) ++ return CURLE_OUT_OF_MEMORY; ++ ++ /* the default methods just call down to the lower I/O layer */ ++ memcpy(&nspr_io_methods, PR_GetDefaultIOMethods(), sizeof nspr_io_methods); ++ ++ /* override certain methods in the table by our wrappers */ ++ nspr_io_methods.recv = nspr_io_recv; ++ nspr_io_methods.send = nspr_io_send; ++ nspr_io_methods.close = nspr_io_close; ++ } ++ + rv = nss_init_core(data, cert_dir); + if(rv) + return rv; +@@ -1273,6 +1346,8 @@ static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl, + static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) + { + PRFileDesc *model = NULL; ++ PRFileDesc *nspr_io = NULL; ++ PRFileDesc *nspr_io_stub = NULL; + PRBool ssl_no_cache; + PRBool ssl_cbc_random_iv; + struct SessionHandle *data = conn->data; +@@ -1433,11 +1508,34 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) + goto error; + } + +- /* Import our model socket onto the existing file descriptor */ +- connssl->handle = PR_ImportTCPSocket(sockfd); +- connssl->handle = SSL_ImportFD(model, connssl->handle); +- if(!connssl->handle) ++ /* wrap OS file descriptor by NSPR's file descriptor abstraction */ ++ nspr_io = PR_ImportTCPSocket(sockfd); ++ if(!nspr_io) ++ goto error; ++ ++ /* create our own NSPR I/O layer */ ++ nspr_io_stub = PR_CreateIOLayerStub(nspr_io_identity, &nspr_io_methods); ++ if(!nspr_io_stub) { ++ PR_Close(nspr_io); + goto error; ++ } ++ ++ /* make the per-connection data accessible from NSPR I/O callbacks */ ++ nspr_io_stub->secret = (void *)connssl; ++ ++ /* push our new layer to the NSPR I/O stack */ ++ if(PR_PushIOLayer(nspr_io, PR_TOP_IO_LAYER, nspr_io_stub) != PR_SUCCESS) { ++ PR_Close(nspr_io); ++ PR_Close(nspr_io_stub); ++ goto error; ++ } ++ ++ /* import our model socket onto the current I/O stack */ ++ connssl->handle = SSL_ImportFD(model, nspr_io); ++ if(!connssl->handle) { ++ PR_Close(nspr_io); ++ goto error; ++ } + + PR_Close(model); /* We don't need this any more */ + model = NULL; +@@ -1480,7 +1578,7 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) + timeout = PR_MillisecondsToInterval((PRUint32) time_left); + if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) { + if(PR_GetError() == PR_WOULD_BLOCK_ERROR) +- /* TODO: propagate the blocking direction from the NSPR layer */ ++ /* blocking direction is updated by nss_update_connecting_state() */ + return CURLE_AGAIN; + else if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN) + curlerr = CURLE_PEER_FAILED_VERIFICATION; +-- +2.1.0 + + +From 813f39b34ecc2634aa8ff332709ddde9235f6891 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 20 Oct 2014 18:18:57 +0200 +Subject: [PATCH 4/4] nss: reset SSL handshake state machine + +... when the handshake succeeds + +This fixes a connection failure when FTPS handle is reused. + +Upstream-commit: 0aecdf682895b42c25b232e91529f48bdf7738b3 +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index dadeb58..36fa097 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1360,9 +1360,6 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) + SSL_LIBRARY_VERSION_TLS_1_0 /* max */ + }; + +- if(connssl->state == ssl_connection_complete) +- return CURLE_OK; +- + connssl->data = data; + + /* list of all NSS objects we need to destroy in Curl_nss_close() */ +@@ -1587,10 +1584,6 @@ static CURLcode nss_do_connect(struct connectdata *conn, int sockindex) + goto error; + } + +- connssl->state = ssl_connection_complete; +- conn->recv[sockindex] = nss_recv; +- conn->send[sockindex] = nss_send; +- + display_conn_info(conn, connssl->handle); + + if(data->set.str[STRING_SSL_ISSUERCERT]) { +@@ -1626,6 +1619,9 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, + const bool blocking = (done == NULL); + CURLcode rv; + ++ if(connssl->state == ssl_connection_complete) ++ return CURLE_OK; ++ + if(connssl->connecting_state == ssl_connect_1) { + rv = nss_setup_connect(conn, sockindex); + if(rv) +@@ -1665,7 +1661,12 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, + /* signal completed SSL handshake */ + *done = TRUE; + +- connssl->connecting_state = ssl_connect_done; ++ connssl->state = ssl_connection_complete; ++ conn->recv[sockindex] = nss_recv; ++ conn->send[sockindex] = nss_send; ++ ++ /* ssl_connect_done is never used outside, go back to the initial state */ ++ connssl->connecting_state = ssl_connect_1; + return CURLE_OK; + } + +-- +2.1.0 + diff --git a/SOURCES/0024-curl-7.29.0-68f0166a.patch b/SOURCES/0024-curl-7.29.0-68f0166a.patch new file mode 100644 index 0000000..76c6d72 --- /dev/null +++ b/SOURCES/0024-curl-7.29.0-68f0166a.patch @@ -0,0 +1,38 @@ +From 8f10bf46681c17c7dfc9c9109c36d6e3564bd4ed Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 15 May 2014 23:28:31 +0200 +Subject: [PATCH] HTTP: CREDSPERREQUEST is for HTTP too + +Commit 517b06d657ace (in 7.36.0) that brought the CREDSPERREQUEST flag +only set it for HTTPS, making HTTP less good at doing connection re-use +than it should be. Now set it for HTTP as well. + +Simple test case + +"curl -v -u foo:bar localhost --next -u bar:foo localhos" + +Bug: http://curl.haxx.se/mail/lib-2014-05/0127.html +Reported-by: Kamil Dudka + +Upstream-commit: 68f0166a92cff3660993645e9ad278b26d295832 +Signed-off-by: Kamil Dudka +--- + lib/http.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/http.c b/lib/http.c +index c007226..e2448bc 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -118,7 +118,7 @@ const struct Curl_handler Curl_handler_http = { + ZERO_NULL, /* readwrite */ + PORT_HTTP, /* defport */ + CURLPROTO_HTTP, /* protocol */ +- PROTOPT_NONE /* flags */ ++ PROTOPT_CREDSPERREQUEST /* flags */ + }; + + #ifdef USE_SSL +-- +2.1.0 + diff --git a/SOURCES/0025-curl-7.29.0-3f430c9c.patch b/SOURCES/0025-curl-7.29.0-3f430c9c.patch new file mode 100644 index 0000000..2fdbde8 --- /dev/null +++ b/SOURCES/0025-curl-7.29.0-3f430c9c.patch @@ -0,0 +1,173 @@ +From 7ab0810c977cec1135d9b5bd85b012ca9e6173cc Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 29 Oct 2014 14:14:23 +0100 +Subject: [PATCH 1/2] nss: drop the code for libcurl-level downgrade to SSLv3 + +This code was already deactivated by commit +ec783dc142129d3860e542b443caaa78a6172d56. + +Upstream-commit: 3f430c9c3a4e3748bc075b633a9324c5037c9fe7 +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 52 ---------------------------------------------------- + 1 file changed, 52 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 36fa097..0691394 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -835,36 +835,6 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, + return SECSuccess; + } + +-/* This function is supposed to decide, which error codes should be used +- * to conclude server is TLS intolerant. +- * +- * taken from xulrunner - nsNSSIOLayer.cpp +- */ +-static PRBool +-isTLSIntoleranceError(PRInt32 err) +-{ +- switch (err) { +- case SSL_ERROR_BAD_MAC_ALERT: +- case SSL_ERROR_BAD_MAC_READ: +- case SSL_ERROR_HANDSHAKE_FAILURE_ALERT: +- case SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT: +- case SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE: +- case SSL_ERROR_ILLEGAL_PARAMETER_ALERT: +- case SSL_ERROR_NO_CYPHER_OVERLAP: +- case SSL_ERROR_BAD_SERVER: +- case SSL_ERROR_BAD_BLOCK_PADDING: +- case SSL_ERROR_UNSUPPORTED_VERSION: +- case SSL_ERROR_PROTOCOL_VERSION_ALERT: +- case SSL_ERROR_RX_MALFORMED_FINISHED: +- case SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE: +- case SSL_ERROR_DECODE_ERROR_ALERT: +- case SSL_ERROR_RX_UNKNOWN_ALERT: +- return PR_TRUE; +- default: +- return PR_FALSE; +- } +-} +- + /* update blocking direction in case of PR_WOULD_BLOCK_ERROR */ + static void nss_update_connecting_state(ssl_connect_state state, void *secret) + { +@@ -1236,10 +1206,6 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver, + switch (data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: +- if(data->state.ssl_connect_retry) { +- infof(data, "TLS disabled due to previous handshake failure\n"); +- sslver->max = SSL_LIBRARY_VERSION_3_0; +- } + return CURLE_OK; + + case CURL_SSLVERSION_TLSv1: +@@ -1293,12 +1259,8 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, + struct SessionHandle *data, + CURLcode curlerr) + { +- SSLVersionRange sslver; + PRErrorCode err = 0; + +- /* reset the flag to avoid an infinite loop */ +- data->state.ssl_connect_retry = FALSE; +- + if(is_nss_error(curlerr)) { + /* read NSPR error code */ + err = PR_GetError(); +@@ -1315,17 +1277,6 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, + /* cleanup on connection failure */ + Curl_llist_destroy(connssl->obj_list, NULL); + connssl->obj_list = NULL; +- +- if((SSL_VersionRangeGet(connssl->handle, &sslver) == SECSuccess) +- && (sslver.min == SSL_LIBRARY_VERSION_3_0) +- && (sslver.max == SSL_LIBRARY_VERSION_TLS_1_0) +- && isTLSIntoleranceError(err)) { +- /* schedule reconnect through Curl_retry_request() */ +- data->state.ssl_connect_retry = TRUE; +- infof(data, "Error in TLS handshake, trying SSLv3...\n"); +- return CURLE_OK; +- } +- + return curlerr; + } + +@@ -1434,9 +1385,6 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) + infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n"); + #endif + +- /* reset the flag to avoid an infinite loop */ +- data->state.ssl_connect_retry = FALSE; +- + if(data->set.ssl.cipher_list) { + if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) { + curlerr = CURLE_SSL_CIPHER; +-- +2.1.0 + + +From e21cf86258c3cc2042dfb531cbf94ce2f5405d8c Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 29 Oct 2014 14:24:54 +0100 +Subject: [PATCH 2/2] transfer: drop the code handling the ssl_connect_retry + flag + +Its last use has been removed by the previous commit. + +Upstream-commit: 276741af4ddebe0cc0d446712fb8dfdf0c140e7b +Signed-off-by: Kamil Dudka +--- + lib/transfer.c | 12 ++++-------- + lib/urldata.h | 3 --- + 2 files changed, 4 insertions(+), 11 deletions(-) + +diff --git a/lib/transfer.c b/lib/transfer.c +index 330b37a..dff6838 100644 +--- a/lib/transfer.c ++++ b/lib/transfer.c +@@ -1269,8 +1269,6 @@ CURLcode Curl_pretransfer(struct SessionHandle *data) + data->state.errorbuf = FALSE; /* no error has occurred */ + data->state.httpversion = 0; /* don't assume any particular server version */ + +- data->state.ssl_connect_retry = FALSE; +- + data->state.authproblem = FALSE; + data->state.authhost.want = data->set.httpauth; + data->state.authproxy.want = data->set.proxyauth; +@@ -1848,12 +1846,10 @@ CURLcode Curl_retry_request(struct connectdata *conn, + !(conn->handler->protocol&(CURLPROTO_HTTP|CURLPROTO_RTSP))) + return CURLE_OK; + +- if(/* workaround for broken TLS servers */ data->state.ssl_connect_retry || +- ((data->req.bytecount + +- data->req.headerbytecount == 0) && +- conn->bits.reuse && +- !data->set.opt_no_body && +- data->set.rtspreq != RTSPREQ_RECEIVE)) { ++ if((data->req.bytecount + data->req.headerbytecount == 0) && ++ conn->bits.reuse && ++ !data->set.opt_no_body && ++ (data->set.rtspreq != RTSPREQ_RECEIVE)) { + /* We got no data, we attempted to re-use a connection and yet we want a + "body". 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 +diff --git a/lib/urldata.h b/lib/urldata.h +index c91bcff..04f590d 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1288,9 +1288,6 @@ struct UrlState { + } proto; + /* current user of this SessionHandle instance, or NULL */ + struct connectdata *current_conn; +- +- /* if true, force SSL connection retry (workaround for certain servers) */ +- bool ssl_connect_retry; + }; + + +-- +2.1.0 + diff --git a/SOURCES/0026-curl-7.29.0-bc6037ed.patch b/SOURCES/0026-curl-7.29.0-bc6037ed.patch new file mode 100644 index 0000000..3dde385 --- /dev/null +++ b/SOURCES/0026-curl-7.29.0-bc6037ed.patch @@ -0,0 +1,34 @@ +From ea3f4adb3c2b10cfb6b7720a3325cb81569a60a3 Mon Sep 17 00:00:00 2001 +From: Martin Jansen +Date: Wed, 6 Mar 2013 21:20:44 +0100 +Subject: [PATCH] Curl_proxyCONNECT: count received headers + +Proxy servers tend to add their own headers at the beginning of +responses. The size of these headers was not taken into account by +CURLINFO_HEADER_SIZE before this change. + +Bug: http://curl.haxx.se/bug/view.cgi?id=1204 +Upstream-commit: bc6037ed3ec029b9f1372f708521fcada4a74af7 +Signed-off-by: Kamil Dudka +--- + lib/http_proxy.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/http_proxy.c b/lib/http_proxy.c +index 4f17ce2..c2eb667 100644 +--- a/lib/http_proxy.c ++++ b/lib/http_proxy.c +@@ -356,6 +356,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, + + result = Curl_client_write(conn, writetype, line_start, + perline); ++ ++ data->info.header_size += (long)perline; ++ data->req.headerbytecount += (long)perline; ++ + if(result) + return result; + +-- +2.1.0 + diff --git a/SOURCES/0027-curl-7.29.0-63a0bd42.patch b/SOURCES/0027-curl-7.29.0-63a0bd42.patch new file mode 100644 index 0000000..d7be0f1 --- /dev/null +++ b/SOURCES/0027-curl-7.29.0-63a0bd42.patch @@ -0,0 +1,64 @@ +From 2ac0f436a3ed216d3fc634592d302c6b8efe25d0 Mon Sep 17 00:00:00 2001 +From: Frank Meier +Date: Fri, 22 Aug 2014 14:54:41 +0200 +Subject: [PATCH] NTLM: ignore CURLOPT_FORBID_REUSE during NTLM HTTP auth + +Problem: if CURLOPT_FORBID_REUSE is set, requests using NTLM failed +since NTLM requires multiple requests that re-use the same connection +for the authentication to work + +Solution: Ignore the forbid reuse flag in case the NTLM authentication +handshake is in progress, according to the NTLM state flag. + +Fixed known bug #77. + +Upstream-commit: 63a0bd4270decef04e64fbe497b42f2c9e26c62b +Signed-off-by: Kamil Dudka +--- + docs/KNOWN_BUGS | 4 ---- + lib/url.c | 7 +++++-- + 2 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS +index d363827..170987e 100644 +--- a/docs/KNOWN_BUGS ++++ b/docs/KNOWN_BUGS +@@ -18,10 +18,6 @@ may have been fixed since this was written! + any file at all. Like when using FTP. + http://curl.haxx.se/bug/view.cgi?id=3438362 + +-77. CURLOPT_FORBID_REUSE on a handle prevents NTLM from working since it +- "abuses" the underlying connection re-use system and if connections are +- forced to close they break the NTLM support. +- + 76. The SOCKET type in Win64 is 64 bits large (and thus so is curl_socket_t on + that platform), and long is only 32 bits. It makes it impossible for + curl_easy_getinfo() to return a socket properly with the CURLINFO_LASTSOCKET +diff --git a/lib/url.c b/lib/url.c +index de8e153..5fcef89 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -5252,7 +5252,8 @@ CURLcode Curl_done(struct connectdata **connp, + } + + /* if data->set.reuse_forbid is TRUE, it means the libcurl client has +- forced us to close this no matter what we think. ++ forced us to close this connection. This is ignored for requests taking ++ place in a NTLM authentication handshake + + if conn->bits.close is TRUE, it means that the connection should be + closed in spite of all our efforts to be nice, due to protocol +@@ -5267,7 +5268,9 @@ CURLcode Curl_done(struct connectdata **connp, + connection_id == -1 here means that the connection has not been added + to the connection cache (OOM) and thus we must disconnect it here. + */ +- if(data->set.reuse_forbid || conn->bits.close || premature || ++ if((data->set.reuse_forbid && !(conn->ntlm.state == NTLMSTATE_TYPE2 || ++ conn->proxyntlm.state == NTLMSTATE_TYPE2)) ++ || conn->bits.close || premature || + (-1 == conn->connection_id)) { + CURLcode res2 = Curl_disconnect(conn, premature); /* close connection */ + +-- +2.1.0 + diff --git a/SOURCES/0028-curl-7.29.0-CVE-2014-3613.patch b/SOURCES/0028-curl-7.29.0-CVE-2014-3613.patch new file mode 100644 index 0000000..f1973f1 --- /dev/null +++ b/SOURCES/0028-curl-7.29.0-CVE-2014-3613.patch @@ -0,0 +1,1408 @@ +From 4ce37d79704623778fbe266397c85ed2b735e4dd Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 15 Mar 2013 14:18:16 +0100 +Subject: [PATCH 1/7] HTTP proxy: insert slash in URL if missing + +curl has been accepting URLs using slightly wrong syntax for a long +time, such as when completely missing as slash "http://example.org" or +missing a slash when a query part is given +"http://example.org?q=foobar". + +curl would translate these into a legitimate HTTP request to servers, +although as was shown in bug #1206 it was not adjusted properly in the +cases where a HTTP proxy was used. + +Test 1213 and 1214 were added to the test suite to verify this fix. + +The test HTTP server was adjusted to allow us to specify test number in +the host name only without using any slashes in a given URL. + +Bug: http://curl.haxx.se/bug/view.cgi?id=1206 +Reported by: ScottJi + +Upstream-commit: e4b733e3f1a771bd1017cdcfb355fcb9caffe646 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 38 ++++++++++++++++++++++++++++++++++ + tests/FILEFORMAT | 4 ++++ + tests/data/Makefile.am | 2 +- + tests/data/Makefile.in | 2 +- + tests/data/test1213 | 53 +++++++++++++++++++++++++++++++++++++++++++++++ + tests/data/test1214 | 53 +++++++++++++++++++++++++++++++++++++++++++++++ + tests/server/sws.c | 56 ++++++++++++++++++++++++++++++++++++++++++-------- + 7 files changed, 198 insertions(+), 10 deletions(-) + create mode 100644 tests/data/test1213 + create mode 100644 tests/data/test1214 + +diff --git a/lib/url.c b/lib/url.c +index 181f0a4..77549ba 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -3584,6 +3584,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data, + char protobuf[16]; + const char *protop; + CURLcode result; ++ bool fix_slash = FALSE; + + *prot_missing = FALSE; + +@@ -3730,12 +3731,14 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data, + memcpy(path+1, query, hostlen); + + path[0]='/'; /* prepend the missing slash */ ++ fix_slash = TRUE; + + *query=0; /* now cut off the hostname at the ? */ + } + else if(!path[0]) { + /* if there's no path set, use a single slash */ + strcpy(path, "/"); ++ fix_slash = TRUE; + } + + /* If the URL is malformatted (missing a '/' after hostname before path) we +@@ -3748,6 +3751,41 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data, + is bigger than the path. Use +1 to move the zero byte too. */ + memmove(&path[1], path, strlen(path)+1); + path[0] = '/'; ++ fix_slash = TRUE; ++ } ++ ++ ++ /* ++ * "fix_slash" means that the URL was malformatted so we need to generate an ++ * updated version with the new slash inserted at the right place! We need ++ * the corrected URL when communicating over HTTP proxy and we don't know at ++ * this point if we're using a proxy or not. ++ */ ++ if(fix_slash) { ++ char *reurl; ++ ++ size_t plen = strlen(path); /* new path, should be 1 byte longer than ++ the original */ ++ size_t urllen = strlen(data->change.url); /* original URL length */ ++ ++ reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */ ++ if(!reurl) ++ return CURLE_OUT_OF_MEMORY; ++ ++ /* copy the prefix */ ++ memcpy(reurl, data->change.url, urllen - (plen-1)); ++ ++ /* append the trailing piece + zerobyte */ ++ memcpy(&reurl[urllen - (plen-1)], path, plen + 1); ++ ++ /* possible free the old one */ ++ if(data->change.url_alloc) { ++ Curl_safefree(data->change.url); ++ data->change.url_alloc = FALSE; ++ } ++ ++ data->change.url = reurl; ++ data->change.url_alloc = TRUE; /* free this later */ + } + + /************************************************************* +diff --git a/tests/FILEFORMAT b/tests/FILEFORMAT +index d79cbf7..96cd5c8 100644 +--- a/tests/FILEFORMAT ++++ b/tests/FILEFORMAT +@@ -250,6 +250,10 @@ If a CONNECT is used to the server (to emulate HTTPS etc over proxy), the port + number given in the CONNECT request will be used to identify which test that + is being run, if the proxy host name is said to start with 'test'. + ++If there's no non-zero test number found in the above to places, the HTTP test ++server will use the number following the last dot in the given url so that ++"foo.bar.123" gets treated as test case 123. ++ + Set type="perl" to write the test case as a perl script. It implies that + there's no memory debugging and valgrind gets shut off for this test. + +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 4e37ed9..5e12f62 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -77,7 +77,7 @@ test1110 test1111 test1112 test1113 test1114 test1115 test1116 test1117 \ + test1118 test1119 test1120 test1121 test1122 test1123 test1124 test1125 \ + test1126 test1127 test1128 test1129 test1130 test1131 test1132 test1133 \ + test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \ +-test1208 test1209 test1210 test1211 test1216 test1218 \ ++test1208 test1209 test1210 test1211 test1213 test1214 test1216 test1218 \ + test1220 test1221 test1222 test1223 test1233 \ + test1300 test1301 test1302 test1303 test1304 test1305 \ + test1306 test1307 test1308 test1309 test1310 test1311 test1312 test1313 \ +diff --git a/tests/data/Makefile.in b/tests/data/Makefile.in +index d7f9ac2..597c1fb 100644 +--- a/tests/data/Makefile.in ++++ b/tests/data/Makefile.in +@@ -341,7 +341,7 @@ test1110 test1111 test1112 test1113 test1114 test1115 test1116 test1117 \ + test1118 test1119 test1120 test1121 test1122 test1123 test1124 test1125 \ + test1126 test1127 test1128 test1129 test1130 test1131 test1132 test1133 \ + test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \ +-test1208 test1209 test1210 test1211 test1216 test1218 \ ++test1208 test1209 test1210 test1211 test1213 test1214 test1216 test1218 \ + test1220 test1221 test1222 test1223 \ + test1300 test1301 test1302 test1303 test1304 test1305 \ + test1306 test1307 test1308 test1309 test1310 test1311 test1312 test1313 \ +diff --git a/tests/data/test1213 b/tests/data/test1213 +new file mode 100644 +index 0000000..d0d12b4 +--- /dev/null ++++ b/tests/data/test1213 +@@ -0,0 +1,53 @@ ++ ++ ++ ++HTTP ++HTTP GET ++HTTP proxy ++ ++ ++ ++# Server-side ++ ++ ++HTTP/1.1 200 OK ++Date: Thu, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Type: text/html ++Funny-head: yesyes ++Content-Length: 22 ++ ++the content goes here ++ ++ ++ ++# Client-side ++ ++ ++http ++ ++ ++HTTP with proxy and host-only URL ++ ++# the thing here is that this sloppy form is accepted and we convert it ++# for normal server use, and we need to make sure it gets converted to ++# RFC style even for proxies ++ ++-x %HOSTIP:%HTTPPORT we.want.that.site.com.1213 ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++^User-Agent:.* ++ ++ ++GET HTTP://we.want.that.site.com.1213/ HTTP/1.1 ++Host: we.want.that.site.com.1213 ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++ ++ ++ +diff --git a/tests/data/test1214 b/tests/data/test1214 +new file mode 100644 +index 0000000..8c36ade +--- /dev/null ++++ b/tests/data/test1214 +@@ -0,0 +1,53 @@ ++ ++ ++ ++HTTP ++HTTP GET ++HTTP proxy ++ ++ ++ ++# Server-side ++ ++ ++HTTP/1.1 200 OK ++Date: Thu, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Type: text/html ++Funny-head: yesyes ++Content-Length: 22 ++ ++the content goes here ++ ++ ++ ++# Client-side ++ ++ ++http ++ ++ ++HTTP with proxy and URL with ? and no slash separator ++ ++# the thing here is that this sloppy form is accepted and we convert it ++# for normal server use, and we need to make sure it gets converted to ++# RFC style even for proxies ++ ++-x %HOSTIP:%HTTPPORT http://we.want.that.site.com.1214?moo=foo ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++^User-Agent:.* ++ ++ ++GET http://we.want.that.site.com.1214/?moo=foo HTTP/1.1 ++Host: we.want.that.site.com.1214 ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++ ++ ++ +diff --git a/tests/server/sws.c b/tests/server/sws.c +index a7de09f..aef55ea 100644 +--- a/tests/server/sws.c ++++ b/tests/server/sws.c +@@ -507,15 +507,24 @@ static int ProcessRequest(struct httprequest *req) + else + req->partno = 0; + +- sprintf(logbuf, "Requested test number %ld part %ld", +- req->testno, req->partno); +- logmsg("%s", logbuf); ++ if(req->testno) { ++ ++ sprintf(logbuf, "Requested test number %ld part %ld", ++ req->testno, req->partno); ++ logmsg("%s", logbuf); + +- /* find and parse for this test */ +- parse_servercmd(req); ++ /* find and parse for this test */ ++ parse_servercmd(req); ++ } ++ else ++ req->testno = DOCNUMBER_NOTHING; + + } +- else { ++ ++ if(req->testno == DOCNUMBER_NOTHING) { ++ /* didn't find any in the first scan, try alternative test case ++ number placements */ ++ + if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d", + doc, &prot_major, &prot_minor) == 3) { + char *portp = NULL; +@@ -563,8 +572,39 @@ static int ProcessRequest(struct httprequest *req) + parse_servercmd(req); + } + else { +- logmsg("Did not find test number in PATH"); +- req->testno = DOCNUMBER_404; ++ /* there was no trailing slash and it wasn't CONNECT, then we get the ++ the number off the last dot instead, IE we consider the TLD to be ++ the test number. Test 123 can then be written as ++ "example.com.123". */ ++ ++ /* find the last dot */ ++ ptr = strrchr(doc, '.'); ++ ++ /* get the number after it */ ++ if(ptr) { ++ ptr++; /* skip the dot */ ++ ++ req->testno = strtol(ptr, &ptr, 10); ++ ++ if(req->testno > 10000) { ++ req->partno = req->testno % 10000; ++ req->testno /= 10000; ++ } ++ else ++ req->partno = 0; ++ ++ sprintf(logbuf, "Requested test number %ld part %ld (from host name)", ++ req->testno, req->partno); ++ logmsg("%s", logbuf); ++ ++ } ++ ++ if(!req->testno) { ++ logmsg("Did not find test number in PATH"); ++ req->testno = DOCNUMBER_404; ++ } ++ else ++ parse_servercmd(req); + } + } + } +-- +2.1.0 + + +From 052143a4aaac9ce91ffdb6ae88eb5888c54d66aa Mon Sep 17 00:00:00 2001 +From: YAMADA Yasuharu +Date: Sat, 18 May 2013 22:51:31 +0200 +Subject: [PATCH 2/7] cookies: only consider full path matches + +I found a bug which cURL sends cookies to the path not to aim at. +For example: +- cURL sends a request to http://example.fake/hoge/ +- server returns cookie which with path=/hoge; + the point is there is NOT the '/' end of path string. +- cURL sends a request to http://example.fake/hogege/ with the cookie. + +The reason for this old "feature" is because that behavior is what is +described in the original netscape cookie spec: +http://curl.haxx.se/rfc/cookie_spec.html + +The current cookie spec (RFC6265) clarifies the situation: +http://tools.ietf.org/html/rfc6265#section-5.2.4 +Upstream-commit: 04f52e9b4db01bcbf672c9c69303a4e4ad0d0fb9 +Signed-off-by: Kamil Dudka +--- + lib/cookie.c | 33 ++++++++++++++++++++++++++---- + tests/data/Makefile.am | 2 +- + tests/data/Makefile.in | 2 +- + tests/data/test1228 | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ + tests/data/test46 | 8 ++++---- + tests/data/test8 | 2 +- + 6 files changed, 90 insertions(+), 11 deletions(-) + create mode 100644 tests/data/test1228 + +diff --git a/lib/cookie.c b/lib/cookie.c +index ac4d89c..a4480c0 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -143,6 +143,34 @@ static bool tailmatch(const char *cooke_domain, const char *hostname) + return FALSE; + } + ++static bool pathmatch(const char* cookie_path, const char* url_path) ++{ ++ size_t cookie_path_len = strlen(cookie_path); ++ size_t url_path_len = strlen(url_path); ++ ++ if(url_path_len < cookie_path_len) ++ return FALSE; ++ ++ /* not using checkprefix() because matching should be case-sensitive */ ++ if(strncmp(cookie_path, url_path, cookie_path_len)) ++ return FALSE; ++ ++ /* it is true if cookie_path and url_path are the same */ ++ if(cookie_path_len == url_path_len) ++ return TRUE; ++ ++ /* here, cookie_path_len < url_path_len */ ++ ++ /* it is false if cookie path is /example and url path is /examples */ ++ if(cookie_path[cookie_path_len - 1] != '/') { ++ if(url_path[cookie_path_len] != '/') { ++ return FALSE; ++ } ++ } ++ /* matching! */ ++ return TRUE; ++} ++ + /* + * Load cookies from all given cookie files (CURLOPT_COOKIEFILE). + */ +@@ -841,10 +869,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, + + /* now check the left part of the path with the cookies path + requirement */ +- if(!co->path || +- /* not using checkprefix() because matching should be +- case-sensitive */ +- !strncmp(co->path, path, strlen(co->path)) ) { ++ if(!co->path || pathmatch(co->path, path) ) { + + /* and now, we know this is a match and we should create an + entry for the return-linked-list */ +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 4e37ed9..64662c6 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -78,7 +78,7 @@ test1118 test1119 test1120 test1121 test1122 test1123 test1124 test1125 \ + test1126 test1127 test1128 test1129 test1130 test1131 test1132 test1133 \ + test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \ + test1208 test1209 test1210 test1211 test1213 test1214 test1216 test1218 \ +-test1220 test1221 test1222 test1223 test1233 \ ++test1220 test1221 test1222 test1223 test1233 test1236 \ + test1300 test1301 test1302 test1303 test1304 test1305 \ + test1306 test1307 test1308 test1309 test1310 test1311 test1312 test1313 \ + test1314 test1315 test1316 test1317 test1318 test1319 test1320 test1321 \ +diff --git a/tests/data/Makefile.in b/tests/data/Makefile.in +index 1e6d679..5296c09 100644 +--- a/tests/data/Makefile.in ++++ b/tests/data/Makefile.in +@@ -342,7 +342,7 @@ test1118 test1119 test1120 test1121 test1122 test1123 test1124 test1125 \ + test1126 test1127 test1128 test1129 test1130 test1131 test1132 test1133 \ + test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \ + test1208 test1209 test1210 test1211 test1213 test1214 test1216 test1218 \ +-test1220 test1221 test1222 test1223 \ ++test1220 test1221 test1222 test1223 test1233 test1236 \ + test1300 test1301 test1302 test1303 test1304 test1305 \ + test1306 test1307 test1308 test1309 test1310 test1311 test1312 test1313 \ + test1314 test1315 test1316 test1317 test1318 test1319 test1320 test1321 \ +diff --git a/tests/data/test1228 b/tests/data/test1228 +new file mode 100644 +index 0000000..0a76b87 +--- /dev/null ++++ b/tests/data/test1228 +@@ -0,0 +1,54 @@ ++ ++ ++ ++HTTP ++HTTP GET ++cookies ++cookie path ++ ++ ++ ++ ++HTTP/1.1 200 OK ++Date: Tue, 25 Sep 2001 19:37:44 GMT ++Set-Cookie: path1=root; domain=.example.fake; path=/; ++Set-Cookie: path2=depth1; domain=.example.fake; path=/hoge; ++Content-Length: 34 ++ ++This server says cookie path test ++ ++ ++ ++# Client-side ++ ++ ++http ++ ++ ++HTTP cookie path match ++ ++ ++http://example.fake/hoge/1228 http://example.fake/hogege/ -b nonexisting -x %HOSTIP:%HTTPPORT ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++^User-Agent:.* ++ ++ ++GET http://example.fake/hoge/1228 HTTP/1.1 ++Host: example.fake ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++GET http://example.fake/hogege/ HTTP/1.1 ++Host: example.fake ++Accept: */* ++Proxy-Connection: Keep-Alive ++Cookie: path1=root ++ ++ ++ ++ +diff --git a/tests/data/test46 b/tests/data/test46 +index f73acde..b6f8f83 100644 +--- a/tests/data/test46 ++++ b/tests/data/test46 +@@ -52,8 +52,8 @@ TZ=GMT + www.fake.come FALSE / FALSE 1022144953 cookiecliente si + www.loser.com FALSE / FALSE 1139150993 UID 99 + %HOSTIP FALSE / FALSE 1439150993 mooo indeed +-#HttpOnly_%HOSTIP FALSE /w FALSE 1439150993 mooo2 indeed2 +-%HOSTIP FALSE /wa FALSE 0 empty ++#HttpOnly_%HOSTIP FALSE /want FALSE 1439150993 mooo2 indeed2 ++%HOSTIP FALSE /want FALSE 0 empty + + + +@@ -77,8 +77,8 @@ Cookie: empty=; mooo2=indeed2; mooo=indeed + www.fake.come FALSE / FALSE 1022144953 cookiecliente si + www.loser.com FALSE / FALSE 1139150993 UID 99 + %HOSTIP FALSE / FALSE 1439150993 mooo indeed +-#HttpOnly_%HOSTIP FALSE /w FALSE 1439150993 mooo2 indeed2 +-%HOSTIP FALSE /wa FALSE 0 empty ++#HttpOnly_%HOSTIP FALSE /want FALSE 1439150993 mooo2 indeed2 ++%HOSTIP FALSE /want FALSE 0 empty + %HOSTIP FALSE / FALSE 2054030187 ckyPersistent permanent + %HOSTIP FALSE / FALSE 0 ckySession temporary + %HOSTIP FALSE / FALSE 0 ASPSESSIONIDQGGQQSJJ GKNBDIFAAOFDPDAIEAKDIBKE +diff --git a/tests/data/test8 b/tests/data/test8 +index c36408a..4d54541 100644 +--- a/tests/data/test8 ++++ b/tests/data/test8 +@@ -59,7 +59,7 @@ perl -e 'if ("%HOSTIP" !~ /\.0\.0\.1$/) {print "Test only works for HOSTIPs endi + GET /we/want/8 HTTP/1.1 + Host: %HOSTIP:%HTTPPORT + Accept: */* +-Cookie: cookie=perhaps; cookie=yes; partmatch=present; foobar=name; blexp=yesyes ++Cookie: cookie=perhaps; cookie=yes; foobar=name; blexp=yesyes + + + +-- +2.1.0 + + +From 847085920706380e75f8cb23f2a161cdcdfcb384 Mon Sep 17 00:00:00 2001 +From: YAMADA Yasuharu +Date: Wed, 12 Jun 2013 11:19:56 +0200 +Subject: [PATCH 3/7] cookies: follow-up fix for path checking + +The initial fix to only compare full path names were done in commit +04f52e9b4db0 but found out to be incomplete. This takes should make the +change more complete and there's now two additional tests to verify +(test 31 and 62). +Upstream-commit: f24dc09d209a2f91ca38d854f0c15ad93f3d7e2d +Signed-off-by: Kamil Dudka +--- + lib/cookie.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++-------- + lib/cookie.h | 3 +- + tests/data/test31 | 3 ++ + 3 files changed, 128 insertions(+), 21 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index a4480c0..1d226cf 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -106,6 +106,8 @@ static void freecookie(struct Cookie *co) + free(co->domain); + if(co->path) + free(co->path); ++ if(co->spath) ++ free(co->spath); + if(co->name) + free(co->name); + if(co->value) +@@ -143,32 +145,114 @@ static bool tailmatch(const char *cooke_domain, const char *hostname) + return FALSE; + } + +-static bool pathmatch(const char* cookie_path, const char* url_path) ++/* ++ * matching cookie path and url path ++ * RFC6265 5.1.4 Paths and Path-Match ++ */ ++static bool pathmatch(const char* cookie_path, const char* request_uri) + { +- size_t cookie_path_len = strlen(cookie_path); +- size_t url_path_len = strlen(url_path); ++ size_t cookie_path_len; ++ size_t uri_path_len; ++ char* uri_path = NULL; ++ char* pos; ++ bool ret = FALSE; ++ ++ /* cookie_path must not have last '/' separator. ex: /sample */ ++ cookie_path_len = strlen(cookie_path); ++ if(1 == cookie_path_len) { ++ /* cookie_path must be '/' */ ++ return TRUE; ++ } + +- if(url_path_len < cookie_path_len) ++ uri_path = strdup(request_uri); ++ if(!uri_path) + return FALSE; ++ pos = strchr(uri_path, '?'); ++ if(pos) ++ *pos = 0x0; ++ ++ /* #-fragments are already cut off! */ ++ if(0 == strlen(uri_path) || uri_path[0] != '/') { ++ free(uri_path); ++ uri_path = strdup("/"); ++ if(!uri_path) ++ return FALSE; ++ } ++ ++ /* here, RFC6265 5.1.4 says ++ 4. Output the characters of the uri-path from the first character up ++ to, but not including, the right-most %x2F ("/"). ++ but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site ++ without redirect. ++ Ignore this algorithm because /hoge is uri path for this case ++ (uri path is not /). ++ */ ++ ++ uri_path_len = strlen(uri_path); ++ ++ if(uri_path_len < cookie_path_len) { ++ ret = FALSE; ++ goto pathmatched; ++ } + + /* not using checkprefix() because matching should be case-sensitive */ +- if(strncmp(cookie_path, url_path, cookie_path_len)) +- return FALSE; ++ if(strncmp(cookie_path, uri_path, cookie_path_len)) { ++ ret = FALSE; ++ goto pathmatched; ++ } + +- /* it is true if cookie_path and url_path are the same */ +- if(cookie_path_len == url_path_len) +- return TRUE; ++ /* The cookie-path and the uri-path are identical. */ ++ if(cookie_path_len == uri_path_len) { ++ ret = TRUE; ++ goto pathmatched; ++ } + + /* here, cookie_path_len < url_path_len */ ++ if(uri_path[cookie_path_len] == '/') { ++ ret = TRUE; ++ goto pathmatched; ++ } + +- /* it is false if cookie path is /example and url path is /examples */ +- if(cookie_path[cookie_path_len - 1] != '/') { +- if(url_path[cookie_path_len] != '/') { +- return FALSE; +- } ++ ret = FALSE; ++ ++pathmatched: ++ free(uri_path); ++ return ret; ++} ++ ++/* ++ * cookie path sanitize ++ */ ++static char *sanitize_cookie_path(const char *cookie_path) ++{ ++ size_t len; ++ char *new_path = strdup(cookie_path); ++ if(!new_path) ++ return NULL; ++ ++ /* some stupid site sends path attribute with '"'. */ ++ if(new_path[0] == '\"') { ++ memmove((void *)new_path, (const void *)(new_path + 1), strlen(new_path)); ++ } ++ if(new_path[strlen(new_path) - 1] == '\"') { ++ new_path[strlen(new_path) - 1] = 0x0; ++ } ++ ++ /* RFC6265 5.2.4 The Path Attribute */ ++ if(new_path[0] != '/') { ++ /* Let cookie-path be the default-path. */ ++ free(new_path); ++ new_path = strdup("/"); ++ return new_path; ++ } ++ ++ /* convert /hoge/ to /hoge */ ++ len = strlen(new_path); ++ if(1 < len && new_path[len - 1] == '/') { ++ new_path[len - 1] = 0x0; + } +- /* matching! */ +- return TRUE; ++ ++ return new_path; + } + + /* +@@ -316,6 +400,11 @@ Curl_cookie_add(struct SessionHandle *data, + badcookie = TRUE; /* out of memory bad */ + break; + } ++ co->spath = sanitize_cookie_path(co->path); ++ if(!co->spath) { ++ badcookie = TRUE; /* out of memory bad */ ++ break; ++ } + } + else if(Curl_raw_equal("domain", name)) { + /* note that this name may or may not have a preceding dot, but +@@ -489,6 +578,9 @@ Curl_cookie_add(struct SessionHandle *data, + if(co->path) { + memcpy(co->path, path, pathlen); + co->path[pathlen]=0; /* zero terminate */ ++ co->spath = sanitize_cookie_path(co->path); ++ if(!co->spath) ++ badcookie = TRUE; /* out of memory bad */ + } + else + badcookie = TRUE; +@@ -580,12 +672,21 @@ Curl_cookie_add(struct SessionHandle *data, + co->path = strdup(ptr); + if(!co->path) + badcookie = TRUE; ++ else { ++ co->spath = sanitize_cookie_path(co->path); ++ if(!co->spath) { ++ badcookie = TRUE; /* out of memory bad */ ++ } ++ } + break; + } + /* this doesn't look like a path, make one up! */ + co->path = strdup("/"); + if(!co->path) + badcookie = TRUE; ++ co->spath = strdup("/"); ++ if(!co->spath) ++ badcookie = TRUE; + fields++; /* add a field and fall down to secure */ + /* FALLTHROUGH */ + case 3: +@@ -656,14 +757,14 @@ Curl_cookie_add(struct SessionHandle *data, + if(replace_old) { + /* the domains were identical */ + +- if(clist->path && co->path) { +- if(Curl_raw_equal(clist->path, co->path)) { ++ if(clist->spath && co->spath) { ++ if(Curl_raw_equal(clist->spath, co->spath)) { + replace_old = TRUE; + } + else + replace_old = FALSE; + } +- else if(!clist->path && !co->path) ++ else if(!clist->spath && !co->spath) + replace_old = TRUE; + else + replace_old = FALSE; +@@ -692,6 +793,8 @@ Curl_cookie_add(struct SessionHandle *data, + free(clist->domain); + if(clist->path) + free(clist->path); ++ if(clist->spath) ++ free(clist->spath); + if(clist->expirestr) + free(clist->expirestr); + +@@ -869,7 +972,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, + + /* now check the left part of the path with the cookies path + requirement */ +- if(!co->path || pathmatch(co->path, path) ) { ++ if(!co->spath || pathmatch(co->spath, path) ) { + + /* and now, we know this is a match and we should create an + entry for the return-linked-list */ +diff --git a/lib/cookie.h b/lib/cookie.h +index d3b63f7..bd89082 100644 +--- a/lib/cookie.h ++++ b/lib/cookie.h +@@ -29,7 +29,8 @@ struct Cookie { + struct Cookie *next; /* next in the chain */ + char *name; /* = value */ + char *value; /* name = */ +- char *path; /* path = */ ++ char *path; /* path = which is in Set-Cookie: */ ++ char *spath; /* sanitized cookie path */ + char *domain; /* domain = */ + curl_off_t expires; /* expires = */ + char *expirestr; /* the plain text version */ +diff --git a/tests/data/test31 b/tests/data/test31 +index b1171d8..38af83b 100644 +--- a/tests/data/test31 ++++ b/tests/data/test31 +@@ -18,6 +18,8 @@ Content-Type: text/html + Funny-head: yesyes + Set-Cookie: foobar=name; domain=anything.com; path=/ ; secure + Set-Cookie:ismatch=this ; domain=127.0.0.1; path=/silly/ ++Set-Cookie: overwrite=this ; domain=127.0.0.1; path=/overwrite/ ++Set-Cookie: overwrite=this2 ; domain=127.0.0.1; path=/overwrite + Set-Cookie: sec1value=secure1 ; domain=127.0.0.1; path=/secure1/ ; secure + Set-Cookie: sec2value=secure2 ; domain=127.0.0.1; path=/secure2/ ; secure= + Set-Cookie: sec3value=secure3 ; domain=127.0.0.1; path=/secure3/ ; secure= +@@ -94,6 +96,7 @@ Accept: */* + # This file was generated by libcurl! Edit at your own risk. + + .127.0.0.1 TRUE /silly/ FALSE 0 ismatch this ++.127.0.0.1 TRUE /overwrite FALSE 0 overwrite this2 + .127.0.0.1 TRUE /secure1/ TRUE 0 sec1value secure1 + .127.0.0.1 TRUE /secure2/ TRUE 0 sec2value secure2 + .127.0.0.1 TRUE /secure3/ TRUE 0 sec3value secure3 +-- +2.1.0 + + +From ffe02d8f3950b5fcf0470890a112125327606f35 Mon Sep 17 00:00:00 2001 +From: YAMADA Yasuharu +Date: Tue, 17 Sep 2013 15:51:22 +0900 +Subject: [PATCH 4/7] cookies: add expiration + +Implement: Expired Cookies These following situation, curl removes +cookie(s) from struct CookieInfo if the cookie expired. + - Curl_cookie_add() + - Curl_cookie_getlist() + - cookie_output() + +Upstream-commit: 4cfbb201c4f823ba31ba4b895044088fba6ae535 +Signed-off-by: Kamil Dudka +--- + lib/cookie.c | 37 ++++++++++++++++++++++++++ + tests/data/Makefile.am | 2 +- + tests/data/Makefile.in | 2 +- + tests/data/test1415 | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 111 insertions(+), 2 deletions(-) + create mode 100644 tests/data/test1415 + +diff --git a/lib/cookie.c b/lib/cookie.c +index 1d226cf..0ca0829 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -289,6 +289,34 @@ static void strstore(char **str, const char *newstr) + *str = strdup(newstr); + } + ++/* ++ * remove_expired() removes expired cookies. ++ */ ++static void remove_expired(struct CookieInfo *cookies) ++{ ++ struct Cookie *co, *nx, *pv; ++ curl_off_t now = (curl_off_t)time(NULL); ++ ++ co = cookies->cookies; ++ pv = NULL; ++ while(co) { ++ nx = co->next; ++ if((co->expirestr || co->maxage) && co->expires < now) { ++ if(co == cookies->cookies) { ++ cookies->cookies = co->next; ++ } ++ else { ++ pv->next = co->next; ++ } ++ cookies->numcookies--; ++ freecookie(co); ++ } ++ else { ++ pv = co; ++ } ++ co = nx; ++ } ++} + + /**************************************************************************** + * +@@ -740,6 +768,9 @@ Curl_cookie_add(struct SessionHandle *data, + superceeds an already existing cookie, which it may if the previous have + the same domain and path as this */ + ++ /* at first, remove expired cookies */ ++ remove_expired(c); ++ + clist = c->cookies; + replace_old = FALSE; + while(clist) { +@@ -954,6 +985,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, + if(!c || !c->cookies) + return NULL; /* no cookie struct or no cookies in the struct */ + ++ /* at first, remove expired cookies */ ++ remove_expired(c); ++ + co = c->cookies; + + while(co) { +@@ -1196,6 +1230,9 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere) + destination file */ + return 0; + ++ /* at first, remove expired cookies */ ++ remove_expired(c); ++ + if(strequal("-", dumphere)) { + /* use stdout */ + out = stdout; +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 64662c6..f34268c 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -92,7 +92,7 @@ test1371 test1372 test1373 test1374 test1375 test1376 test1377 test1378 \ + test1379 test1380 test1381 test1382 test1383 test1384 test1385 test1386 \ + test1387 test1388 test1389 test1390 test1391 test1392 test1393 \ + test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \ +-test1408 test1409 test1410 test1411 test1412 test1413 \ ++test1408 test1409 test1410 test1411 test1412 test1413 test1415 \ + test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ + test1508 \ + test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \ +diff --git a/tests/data/Makefile.in b/tests/data/Makefile.in +index 791fa1e..cd2c322 100644 +--- a/tests/data/Makefile.in ++++ b/tests/data/Makefile.in +@@ -356,7 +356,7 @@ test1371 test1372 test1373 test1374 test1375 test1376 test1377 test1378 \ + test1379 test1380 test1381 test1382 test1383 test1384 test1385 test1386 \ + test1387 test1388 test1389 test1390 test1391 test1392 test1393 \ + test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \ +-test1408 test1409 test1410 test1411 test1412 test1413 \ ++test1408 test1409 test1410 test1411 test1412 test1413 test1415 \ + test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ + test1508 \ + test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \ +diff --git a/tests/data/test1415 b/tests/data/test1415 +new file mode 100644 +index 0000000..cc6bd70 +--- /dev/null ++++ b/tests/data/test1415 +@@ -0,0 +1,72 @@ ++ ++ ++ ++HTTP ++HTTP GET ++cookies ++cookiejar ++delete expired cookie ++ ++ ++# Server-side ++ ++ ++HTTP/1.1 200 OK ++Date: Thu, 09 Nov 2010 14:49:00 GMT ++Server: test-server/fake ++Content-Length: 4 ++Content-Type: text/html ++Funny-head: yesyes ++Set-Cookie: test1value=test1; domain=example.com; path=/; ++Set-Cookie: test2value=test2; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/; ++Set-Cookie: test3value=test3; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/; ++Set-Cookie: test4value=test4; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/; ++Set-Cookie: test5value=test5; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/; ++Set-Cookie: test6value=test6; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/; ++Set-Cookie: test7value=test7; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/; ++Set-Cookie: test8value=test8; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/; ++ ++boo ++ ++ ++ ++# Client-side ++ ++ ++http ++ ++ ++Delete expired cookies ++ ++ ++TZ=GMT ++ ++ ++http://example.com/we/want/1415 -b none -c log/jar1415.txt -x %HOSTIP:%HTTPPORT ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++^User-Agent:.* ++ ++ ++GET http://example.com/we/want/1415 HTTP/1.1 ++Host: example.com ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++ ++ ++ ++# Netscape HTTP Cookie File ++# http://curl.haxx.se/docs/http-cookies.html ++# This file was generated by libcurl! Edit at your own risk. ++ ++.example.com TRUE / FALSE 0 test1value test1 ++.example.com TRUE / FALSE 2145916800 test2value test2 ++.example.com TRUE / FALSE 2145916800 test4value test4 ++.example.com TRUE / FALSE 2145916800 test7value test7 ++ ++ ++ +-- +2.1.0 + + +From f866a6369316df97b777289a34db03444f7dedbe Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 21 Sep 2013 13:43:39 -0500 +Subject: [PATCH 5/7] test1415: adjusted to work for 32bit time_t + +The libcurl date parser returns INT_MAX for all dates > 2037 so this +test is now made to use 2037 instead of 2038 to work the same for both +32bit and 64bit time_t systems. + +Upstream-commit: 34df869f99477edda61d639151b1edf75998abd9 +Signed-off-by: Kamil Dudka +--- + tests/data/test1415 | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tests/data/test1415 b/tests/data/test1415 +index cc6bd70..51eed3e 100644 +--- a/tests/data/test1415 ++++ b/tests/data/test1415 +@@ -18,12 +18,12 @@ Content-Length: 4 + Content-Type: text/html + Funny-head: yesyes + Set-Cookie: test1value=test1; domain=example.com; path=/; +-Set-Cookie: test2value=test2; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/; ++Set-Cookie: test2value=test2; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/; + Set-Cookie: test3value=test3; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/; +-Set-Cookie: test4value=test4; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/; ++Set-Cookie: test4value=test4; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/; + Set-Cookie: test5value=test5; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/; + Set-Cookie: test6value=test6; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/; +-Set-Cookie: test7value=test7; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/; ++Set-Cookie: test7value=test7; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/; + Set-Cookie: test8value=test8; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/; + + boo +@@ -64,9 +64,9 @@ Proxy-Connection: Keep-Alive + # This file was generated by libcurl! Edit at your own risk. + + .example.com TRUE / FALSE 0 test1value test1 +-.example.com TRUE / FALSE 2145916800 test2value test2 +-.example.com TRUE / FALSE 2145916800 test4value test4 +-.example.com TRUE / FALSE 2145916800 test7value test7 ++.example.com TRUE / FALSE 2114380800 test2value test2 ++.example.com TRUE / FALSE 2114380800 test4value test4 ++.example.com TRUE / FALSE 2114380800 test7value test7 + + + +-- +2.1.0 + + +From 8471ac93e881f7f17fe598086b6b548289716279 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 16 Jan 2014 08:51:30 +0100 +Subject: [PATCH 6/7] cookie: max-age fixes + +1 - allow >31 bit max-age values + +2 - don't overflow on extremely large max-age values when we add the +value to the current time + +3 - make sure max-age takes precedence over expires as dictated by +RFC6265 + +Bug: http://curl.haxx.se/mail/lib-2014-01/0130.html +Reported-by: Chen Prog +Upstream-commit: ecaf2f02f1df70f0bbcbbbf48914bfc83c8f2a56 +Signed-off-by: Kamil Dudka +--- + lib/cookie.c | 38 ++++++++++++++++++++++++-------------- + 1 file changed, 24 insertions(+), 14 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index 0ca0829..d4fe9a3 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -523,9 +523,6 @@ Curl_cookie_add(struct SessionHandle *data, + badcookie = TRUE; + break; + } +- co->expires = +- strtol((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0],NULL,10) +- + (long)now; + } + else if(Curl_raw_equal("expires", name)) { + strstore(&co->expirestr, whatptr); +@@ -533,17 +530,6 @@ Curl_cookie_add(struct SessionHandle *data, + badcookie = TRUE; + break; + } +- /* Note that if the date couldn't get parsed for whatever reason, +- the cookie will be treated as a session cookie */ +- co->expires = curl_getdate(what, &now); +- +- /* Session cookies have expires set to 0 so if we get that back +- from the date parser let's add a second to make it a +- non-session cookie */ +- if(co->expires == 0) +- co->expires = 1; +- else if(co->expires < 0) +- co->expires = 0; + } + else if(!co->name) { + co->name = strdup(name); +@@ -578,6 +564,30 @@ Curl_cookie_add(struct SessionHandle *data, + semiptr=strchr(ptr, '\0'); + } while(semiptr); + ++ if(co->maxage) { ++ co->expires = ++ curlx_strtoofft((*co->maxage=='\"')? ++ &co->maxage[1]:&co->maxage[0], NULL, 10); ++ if(CURL_OFF_T_MAX - now < co->expires) ++ /* avoid overflow */ ++ co->expires = CURL_OFF_T_MAX; ++ else ++ co->expires += now; ++ } ++ else if(co->expirestr) { ++ /* Note that if the date couldn't get parsed for whatever reason, ++ the cookie will be treated as a session cookie */ ++ co->expires = curl_getdate(co->expirestr, NULL); ++ ++ /* Session cookies have expires set to 0 so if we get that back ++ from the date parser let's add a second to make it a ++ non-session cookie */ ++ if(co->expires == 0) ++ co->expires = 1; ++ else if(co->expires < 0) ++ co->expires = 0; ++ } ++ + if(!badcookie && !co->domain) { + if(domain) { + /* no domain was given in the header line, set the default */ +-- +2.1.0 + + +From ee52a81c23b918895b363b904ebb5fc9908b55cc Mon Sep 17 00:00:00 2001 +From: Tim Ruehsen +Date: Tue, 19 Aug 2014 21:01:28 +0200 +Subject: [PATCH 7/7] cookies: only use full host matches for hosts used as IP + address + +By not detecting and rejecting domain names for partial literal IP +addresses properly when parsing received HTTP cookies, libcurl can be +fooled to both send cookies to wrong sites and to allow arbitrary sites +to set cookies for others. + +CVE-2014-3613 + +Bug: http://curl.haxx.se/docs/adv_20140910A.html +Upstream-commit: 8a75dbeb2305297640453029b7905ef51b87e8dd +Signed-off-by: Kamil Dudka +--- + lib/cookie.c | 50 ++++++++++++++++++++++++++++++++++++++---------- + tests/data/test1105 | 3 +-- + tests/data/test31 | 55 +++++++++++++++++++++++++++-------------------------- + tests/data/test8 | 3 ++- + 4 files changed, 71 insertions(+), 40 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index d4fe9a3..956efd4 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -94,6 +94,7 @@ Example set of cookies: + #include "strtoofft.h" + #include "rawstr.h" + #include "curl_memrchr.h" ++#include "inet_pton.h" + + /* The last #include file should be: */ + #include "memdebug.h" +@@ -318,6 +319,28 @@ static void remove_expired(struct CookieInfo *cookies) + } + } + ++/* ++ * Return true if the given string is an IP(v4|v6) address. ++ */ ++static bool isip(const char *domain) ++{ ++ struct in_addr addr; ++#ifdef ENABLE_IPV6 ++ struct in6_addr addr6; ++#endif ++ ++ if(Curl_inet_pton(AF_INET, domain, &addr) ++#ifdef ENABLE_IPV6 ++ || Curl_inet_pton(AF_INET6, domain, &addr6) ++#endif ++ ) { ++ /* domain name given as IP address */ ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ + /**************************************************************************** + * + * Curl_cookie_add() +@@ -472,24 +495,27 @@ Curl_cookie_add(struct SessionHandle *data, + whatptr); + } + else { ++ bool is_ip; ++ + /* Now, we make sure that our host is within the given domain, + or the given domain is not valid and thus cannot be set. */ + + if('.' == whatptr[0]) + whatptr++; /* ignore preceding dot */ + +- if(!domain || tailmatch(whatptr, domain)) { +- const char *tailptr=whatptr; +- if(tailptr[0] == '.') +- tailptr++; +- strstore(&co->domain, tailptr); /* don't prefix w/dots +- internally */ ++ is_ip = isip(domain ? domain : whatptr); ++ ++ if(!domain ++ || (is_ip && !strcmp(whatptr, domain)) ++ || (!is_ip && tailmatch(whatptr, domain))) { ++ strstore(&co->domain, whatptr); + if(!co->domain) { + badcookie = TRUE; + break; + } +- co->tailmatch=TRUE; /* we always do that if the domain name was +- given */ ++ if(!is_ip) ++ co->tailmatch=TRUE; /* we always do that if the domain name was ++ given */ + } + else { + /* we did not get a tailmatch and then the attempted set domain +@@ -991,6 +1017,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, + time_t now = time(NULL); + struct Cookie *mainco=NULL; + size_t matches = 0; ++ bool is_ip; + + if(!c || !c->cookies) + return NULL; /* no cookie struct or no cookies in the struct */ +@@ -998,6 +1025,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, + /* at first, remove expired cookies */ + remove_expired(c); + ++ /* check if host is an IP(v4|v6) address */ ++ is_ip = isip(host); ++ + co = c->cookies; + + while(co) { +@@ -1009,8 +1039,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c, + + /* now check if the domain is correct */ + if(!co->domain || +- (co->tailmatch && tailmatch(co->domain, host)) || +- (!co->tailmatch && Curl_raw_equal(host, co->domain)) ) { ++ (co->tailmatch && !is_ip && tailmatch(co->domain, host)) || ++ ((!co->tailmatch || is_ip) && Curl_raw_equal(host, co->domain)) ) { + /* the right part of the host matches the domain stuff in the + cookie data */ + +diff --git a/tests/data/test1105 b/tests/data/test1105 +index 922346f..ea7b198 100644 +--- a/tests/data/test1105 ++++ b/tests/data/test1105 +@@ -59,8 +59,7 @@ userid=myname&password=mypassword + # This file was generated by libcurl! Edit at your own risk. + + 127.0.0.1 FALSE /we/want/ FALSE 0 foobar name +-.127.0.0.1 TRUE "/silly/" FALSE 0 mismatch this +-.0.0.1 TRUE / FALSE 0 partmatch present ++127.0.0.1 FALSE "/silly/" FALSE 0 mismatch this + + + +diff --git a/tests/data/test31 b/tests/data/test31 +index 38af83b..dfcac04 100644 +--- a/tests/data/test31 ++++ b/tests/data/test31 +@@ -51,7 +51,8 @@ Set-Cookie: novalue; domain=reallysilly + Set-Cookie: test=yes; domain=foo.com; expires=Sat Feb 2 11:56:27 GMT 2030 + Set-Cookie: test2=yes; domain=se; expires=Sat Feb 2 11:56:27 GMT 2030 + Set-Cookie: magic=yessir; path=/silly/; HttpOnly +-Set-Cookie: blexp=yesyes; domain=.0.0.1; domain=.0.0.1; expiry=totally bad; ++Set-Cookie: blexp=yesyes; domain=127.0.0.1; domain=127.0.0.1; expiry=totally bad; ++Set-Cookie: partialip=nono; domain=.0.0.1; + + boo + +@@ -95,34 +96,34 @@ Accept: */* + # http://curl.haxx.se/docs/http-cookies.html + # This file was generated by libcurl! Edit at your own risk. + +-.127.0.0.1 TRUE /silly/ FALSE 0 ismatch this +-.127.0.0.1 TRUE /overwrite FALSE 0 overwrite this2 +-.127.0.0.1 TRUE /secure1/ TRUE 0 sec1value secure1 +-.127.0.0.1 TRUE /secure2/ TRUE 0 sec2value secure2 +-.127.0.0.1 TRUE /secure3/ TRUE 0 sec3value secure3 +-.127.0.0.1 TRUE /secure4/ TRUE 0 sec4value secure4 +-.127.0.0.1 TRUE /secure5/ TRUE 0 sec5value secure5 +-.127.0.0.1 TRUE /secure6/ TRUE 0 sec6value secure6 +-.127.0.0.1 TRUE /secure7/ TRUE 0 sec7value secure7 +-.127.0.0.1 TRUE /secure8/ TRUE 0 sec8value secure8 +-.127.0.0.1 TRUE /secure9/ TRUE 0 secure very1 +-#HttpOnly_.127.0.0.1 TRUE /p1/ FALSE 0 httpo1 value1 +-#HttpOnly_.127.0.0.1 TRUE /p2/ FALSE 0 httpo2 value2 +-#HttpOnly_.127.0.0.1 TRUE /p3/ FALSE 0 httpo3 value3 +-#HttpOnly_.127.0.0.1 TRUE /p4/ FALSE 0 httpo4 value4 +-#HttpOnly_.127.0.0.1 TRUE /p4/ FALSE 0 httponly myvalue1 +-#HttpOnly_.127.0.0.1 TRUE /p4/ TRUE 0 httpandsec myvalue2 +-#HttpOnly_.127.0.0.1 TRUE /p4/ TRUE 0 httpandsec2 myvalue3 +-#HttpOnly_.127.0.0.1 TRUE /p4/ TRUE 0 httpandsec3 myvalue4 +-#HttpOnly_.127.0.0.1 TRUE /p4/ TRUE 0 httpandsec4 myvalue5 +-#HttpOnly_.127.0.0.1 TRUE /p4/ TRUE 0 httpandsec5 myvalue6 +-#HttpOnly_.127.0.0.1 TRUE /p4/ TRUE 0 httpandsec6 myvalue7 +-#HttpOnly_.127.0.0.1 TRUE /p4/ TRUE 0 httpandsec7 myvalue8 +-#HttpOnly_.127.0.0.1 TRUE /p4/ TRUE 0 httpandsec8 myvalue9 +-.127.0.0.1 TRUE / FALSE 0 partmatch present ++127.0.0.1 FALSE /silly/ FALSE 0 ismatch this ++127.0.0.1 FALSE /overwrite FALSE 0 overwrite this2 ++127.0.0.1 FALSE /secure1/ TRUE 0 sec1value secure1 ++127.0.0.1 FALSE /secure2/ TRUE 0 sec2value secure2 ++127.0.0.1 FALSE /secure3/ TRUE 0 sec3value secure3 ++127.0.0.1 FALSE /secure4/ TRUE 0 sec4value secure4 ++127.0.0.1 FALSE /secure5/ TRUE 0 sec5value secure5 ++127.0.0.1 FALSE /secure6/ TRUE 0 sec6value secure6 ++127.0.0.1 FALSE /secure7/ TRUE 0 sec7value secure7 ++127.0.0.1 FALSE /secure8/ TRUE 0 sec8value secure8 ++127.0.0.1 FALSE /secure9/ TRUE 0 secure very1 ++#HttpOnly_127.0.0.1 FALSE /p1/ FALSE 0 httpo1 value1 ++#HttpOnly_127.0.0.1 FALSE /p2/ FALSE 0 httpo2 value2 ++#HttpOnly_127.0.0.1 FALSE /p3/ FALSE 0 httpo3 value3 ++#HttpOnly_127.0.0.1 FALSE /p4/ FALSE 0 httpo4 value4 ++#HttpOnly_127.0.0.1 FALSE /p4/ FALSE 0 httponly myvalue1 ++#HttpOnly_127.0.0.1 FALSE /p4/ TRUE 0 httpandsec myvalue2 ++#HttpOnly_127.0.0.1 FALSE /p4/ TRUE 0 httpandsec2 myvalue3 ++#HttpOnly_127.0.0.1 FALSE /p4/ TRUE 0 httpandsec3 myvalue4 ++#HttpOnly_127.0.0.1 FALSE /p4/ TRUE 0 httpandsec4 myvalue5 ++#HttpOnly_127.0.0.1 FALSE /p4/ TRUE 0 httpandsec5 myvalue6 ++#HttpOnly_127.0.0.1 FALSE /p4/ TRUE 0 httpandsec6 myvalue7 ++#HttpOnly_127.0.0.1 FALSE /p4/ TRUE 0 httpandsec7 myvalue8 ++#HttpOnly_127.0.0.1 FALSE /p4/ TRUE 0 httpandsec8 myvalue9 ++127.0.0.1 FALSE / FALSE 0 partmatch present + 127.0.0.1 FALSE /we/want/ FALSE 2054030187 nodomain value + #HttpOnly_127.0.0.1 FALSE /silly/ FALSE 0 magic yessir +-.0.0.1 TRUE /we/want/ FALSE 0 blexp yesyes ++127.0.0.1 FALSE /we/want/ FALSE 0 blexp yesyes + + + +diff --git a/tests/data/test8 b/tests/data/test8 +index 4d54541..030fd55 100644 +--- a/tests/data/test8 ++++ b/tests/data/test8 +@@ -42,7 +42,8 @@ Set-Cookie: duplicate=test; domain=.0.0.1; domain=.0.0.1; path=/donkey; + Set-Cookie: cookie=yes; path=/we; + Set-Cookie: cookie=perhaps; path=/we/want; + Set-Cookie: nocookie=yes; path=/WE; +-Set-Cookie: blexp=yesyes; domain=.0.0.1; domain=.0.0.1; expiry=totally bad; ++Set-Cookie: blexp=yesyes; domain=%HOSTIP; domain=%HOSTIP; expiry=totally bad; ++Set-Cookie: partialip=nono; domain=.0.0.1; + + + +-- +2.1.0 + diff --git a/SOURCES/0029-curl-7.29.0-CVE-2014-3707.patch b/SOURCES/0029-curl-7.29.0-CVE-2014-3707.patch new file mode 100644 index 0000000..524f276 --- /dev/null +++ b/SOURCES/0029-curl-7.29.0-CVE-2014-3707.patch @@ -0,0 +1,271 @@ +From 45a125c1d6aaa2352c5ec04eecba322930e6d169 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 17 Oct 2014 12:59:32 +0200 +Subject: [PATCH] curl_easy_duphandle: CURLOPT_COPYPOSTFIELDS read out of + bounds + +When duplicating a handle, the data to post was duplicated using +strdup() when it could be binary and contain zeroes and it was not even +zero terminated! This caused read out of bounds crashes/segfaults. + +Bug: http://curl.haxx.se/docs/adv_20141105.html +CVE: CVE-2014-3707 +Reported-By: Symeon Paraschoudis +Upstream-commit: b3875606925536f82fc61f3114ac42f29eaf6945 +Signed-off-by: Kamil Dudka +--- + lib/formdata.c | 50 ++++++++------------------------------------------ + lib/strdup.c | 29 ++++++++++++++++++++++++++--- + lib/strdup.h | 1 + + lib/url.c | 19 +++++++++++++++---- + lib/urldata.h | 11 +++++++++-- + src/Makefile.in | 3 +-- + src/Makefile.inc | 1 - + 7 files changed, 60 insertions(+), 54 deletions(-) + +diff --git a/lib/formdata.c b/lib/formdata.c +index 3260928..050f538 100644 +--- a/lib/formdata.c ++++ b/lib/formdata.c +@@ -39,6 +39,7 @@ + #include "strequal.h" + #include "curl_memory.h" + #include "sendf.h" ++#include "strdup.h" + + #define _MPRINTF_REPLACE /* use our functions only */ + #include +@@ -216,46 +217,6 @@ static const char * ContentTypeForFilename (const char *filename, + + /*************************************************************************** + * +- * memdup() +- * +- * Copies the 'source' data to a newly allocated buffer buffer (that is +- * returned). Uses buffer_length if not null, else uses strlen to determine +- * the length of the buffer to be copied +- * +- * Returns the new pointer or NULL on failure. +- * +- ***************************************************************************/ +-static char *memdup(const char *src, size_t buffer_length) +-{ +- size_t length; +- bool add = FALSE; +- char *buffer; +- +- if(buffer_length) +- length = buffer_length; +- else if(src) { +- length = strlen(src); +- add = TRUE; +- } +- else +- /* no length and a NULL src pointer! */ +- return strdup(""); +- +- buffer = malloc(length+add); +- if(!buffer) +- return NULL; /* fail */ +- +- memcpy(buffer, src, length); +- +- /* if length unknown do null termination */ +- if(add) +- buffer[length] = '\0'; +- +- return buffer; +-} +- +-/*************************************************************************** +- * + * FormAdd() + * + * Stores a formpost parameter and builds the appropriate linked list. +@@ -684,7 +645,10 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, + app passed in a bad combo, so we better check for that first. */ + if(form->name) + /* copy name (without strdup; possibly contains null characters) */ +- form->name = memdup(form->name, form->namelength); ++ form->name = Curl_memdup(form->name, form->namelength? ++ form->namelength: ++ strlen(form->name)+1); ++ + if(!form->name) { + return_value = CURL_FORMADD_MEMORY; + break; +@@ -695,7 +659,9 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, + HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | + HTTPPOST_CALLBACK)) ) { + /* copy value (without strdup; possibly contains null characters) */ +- form->value = memdup(form->value, form->contentslength); ++ form->value = Curl_memdup(form->value, form->contentslength? ++ form->contentslength: ++ strlen(form->value)+1); + if(!form->value) { + return_value = CURL_FORMADD_MEMORY; + break; +diff --git a/lib/strdup.c b/lib/strdup.c +index 3b776b1..14f370f 100644 +--- a/lib/strdup.c ++++ b/lib/strdup.c +@@ -19,12 +19,13 @@ + * KIND, either express or implied. + * + ***************************************************************************/ +-/* +- * This file is 'mem-include-scan' clean. See test 1132. +- */ + #include "curl_setup.h" + + #include "strdup.h" ++#include "curl_memory.h" ++ ++/* The last #include file should be: */ ++#include "memdebug.h" + + #ifndef HAVE_STRDUP + char *curlx_strdup(const char *str) +@@ -50,3 +51,25 @@ char *curlx_strdup(const char *str) + + } + #endif ++ ++/*************************************************************************** ++ * ++ * Curl_memdup(source, length) ++ * ++ * Copies the 'source' data to a newly allocated buffer (that is ++ * returned). Copies 'length' bytes. ++ * ++ * Returns the new pointer or NULL on failure. ++ * ++ ***************************************************************************/ ++char *Curl_memdup(const char *src, size_t length) ++{ ++ char *buffer = malloc(length); ++ if(!buffer) ++ return NULL; /* fail */ ++ ++ memcpy(buffer, src, length); ++ ++ /* if length unknown do null termination */ ++ return buffer; ++} +diff --git a/lib/strdup.h b/lib/strdup.h +index 49af911..36cc430 100644 +--- a/lib/strdup.h ++++ b/lib/strdup.h +@@ -26,5 +26,6 @@ + #ifndef HAVE_STRDUP + extern char *curlx_strdup(const char *str); + #endif ++char *Curl_memdup(const char *src, size_t buffer_length); + + #endif /* HEADER_CURL_STRDUP_H */ +diff --git a/lib/url.c b/lib/url.c +index b0aade1..0aa5a33 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -123,6 +123,7 @@ int curl_win32_idn_to_ascii(const char *in, char **out); + #include "bundles.h" + #include "conncache.h" + #include "multihandle.h" ++#include "strdup.h" + + #define _MPRINTF_REPLACE /* use our functions only */ + #include +@@ -344,14 +345,24 @@ CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src) + memset(dst->set.str, 0, STRING_LAST * sizeof(char *)); + + /* duplicate all strings */ +- for(i=(enum dupstring)0; i< STRING_LAST; i++) { ++ for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) { + r = setstropt(&dst->set.str[i], src->set.str[i]); + if(r != CURLE_OK) +- break; ++ return r; + } + +- /* If a failure occurred, freeing has to be performed externally. */ +- return r; ++ /* duplicate memory areas pointed to */ ++ i = STRING_COPYPOSTFIELDS; ++ if(src->set.postfieldsize && src->set.str[i]) { ++ /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */ ++ dst->set.str[i] = Curl_memdup(src->set.str[i], src->set.postfieldsize); ++ if(!dst->set.str[i]) ++ return CURLE_OUT_OF_MEMORY; ++ /* point to the new copy */ ++ dst->set.postfields = dst->set.str[i]; ++ } ++ ++ return CURLE_OK; + } + + /* +diff --git a/lib/urldata.h b/lib/urldata.h +index 640cbb1..d03440b 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1337,7 +1337,6 @@ enum dupstring { + STRING_KRB_LEVEL, /* krb security level */ + STRING_NETRC_FILE, /* if not NULL, use this instead of trying to find + $HOME/.netrc */ +- STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ + STRING_PROXY, /* proxy to use */ + STRING_SET_RANGE, /* range, if used */ + STRING_SET_REFERER, /* custom string for the HTTP referer field */ +@@ -1376,7 +1375,15 @@ enum dupstring { + STRING_TLSAUTH_PASSWORD, /* TLS auth */ + #endif + +- /* -- end of strings -- */ ++ /* -- end of zero-terminated strings -- */ ++ ++ STRING_LASTZEROTERMINATED, ++ ++ /* -- below this are pointers to binary data that cannot be strdup'ed. ++ Each such pointer must be added manually to Curl_dupset() --- */ ++ ++ STRING_COPYPOSTFIELDS, /* if POST, set the fields' values here */ ++ + STRING_LAST /* not used, just an end-of-list marker */ + }; + +diff --git a/src/Makefile.in b/src/Makefile.in +index 86e3d3a..74e8b9e 100644 +--- a/src/Makefile.in ++++ b/src/Makefile.in +@@ -111,7 +111,7 @@ am__objects_1 = curl-tool_binmode.$(OBJEXT) curl-tool_bname.$(OBJEXT) \ + curl-tool_urlglob.$(OBJEXT) curl-tool_util.$(OBJEXT) \ + curl-tool_vms.$(OBJEXT) curl-tool_writeenv.$(OBJEXT) \ + curl-tool_writeout.$(OBJEXT) curl-tool_xattr.$(OBJEXT) +-am__objects_2 = curl-strtoofft.$(OBJEXT) curl-strdup.$(OBJEXT) \ ++am__objects_2 = curl-strtoofft.$(OBJEXT) \ + curl-rawstr.$(OBJEXT) curl-nonblock.$(OBJEXT) + am__objects_3 = + am_curl_OBJECTS = $(am__objects_1) $(am__objects_2) $(am__objects_3) +@@ -376,7 +376,6 @@ AM_CPPFLAGS = -I$(top_builddir)/include/curl -I$(top_builddir)/include \ + # the official API, but we re-use the code here to avoid duplication. + CURLX_ONES = \ + ../lib/strtoofft.c \ +- ../lib/strdup.c \ + ../lib/rawstr.c \ + ../lib/nonblock.c + +diff --git a/src/Makefile.inc b/src/Makefile.inc +index 3f9044d..ea81000 100644 +--- a/src/Makefile.inc ++++ b/src/Makefile.inc +@@ -11,7 +11,6 @@ + # the official API, but we re-use the code here to avoid duplication. + CURLX_ONES = \ + ../lib/strtoofft.c \ +- ../lib/strdup.c \ + ../lib/rawstr.c \ + ../lib/nonblock.c + +-- +2.1.0 + diff --git a/SOURCES/0030-curl-7.29.0-CVE-2014-8150.patch b/SOURCES/0030-curl-7.29.0-CVE-2014-8150.patch new file mode 100644 index 0000000..9d23afe --- /dev/null +++ b/SOURCES/0030-curl-7.29.0-CVE-2014-8150.patch @@ -0,0 +1,359 @@ +From 77ed36a0e1f604957054a2c25b6556acbd1c9f29 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 25 Dec 2014 23:55:03 +0100 +Subject: [PATCH 1/2] url-parsing: reject CRLFs within URLs + +Bug: http://curl.haxx.se/docs/adv_20150108B.html +Reported-by: Andrey Labunets + +Upstream-commit: 178bd7db34f77e020fb8562890c5625ccbd67093 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/lib/url.c b/lib/url.c +index 0aa5a33..736d5d9 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -3599,6 +3599,13 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data, + + *prot_missing = FALSE; + ++ /* We might pass the entire URL into the request so we need to make sure ++ * there are no bad characters in there.*/ ++ if(strpbrk(data->change.url, "\r\n")) { ++ failf(data, "Illegal characters found in URL"); ++ return CURLE_URL_MALFORMAT; ++ } ++ + /************************************************************* + * Parse the URL. + * +-- +2.1.0 + + +From 916b5628b33bbc8bcad0f4b491089ba555c3dac6 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 25 Dec 2014 23:51:43 +0100 +Subject: [PATCH 2/2] tests: make sure CRLFs can't be used in URLs passed to + proxy + +Bug: http://curl.haxx.se/docs/adv_20150108B.html + +Upstream-commit: 3df8e78860d3a3d3cf95252bd2b4ad5fd53360cd +Signed-off-by: Kamil Dudka +--- + tests/data/Makefile.am | 2 +- + tests/data/Makefile.in | 2 +- + tests/data/test1529 | 43 ++++++++++++++++++++++++++ + tests/libtest/Makefile.in | 77 +++++++++++++++++++++++++++++++++++++++++++++- + tests/libtest/Makefile.inc | 7 ++++- + tests/libtest/lib1529.c | 59 +++++++++++++++++++++++++++++++++++ + 6 files changed, 186 insertions(+), 4 deletions(-) + create mode 100644 tests/data/test1529 + create mode 100644 tests/libtest/lib1529.c + +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 0a767b3..0bb8ffd 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -94,7 +94,7 @@ test1387 test1388 test1389 test1390 test1391 test1392 test1393 \ + test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \ + test1408 test1409 test1410 test1411 test1412 test1413 test1415 \ + test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ +-test1508 \ ++test1508 test1529 \ + test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \ + test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \ + test2016 test2017 test2018 test2019 test2020 test2021 test2022 \ +diff --git a/tests/data/Makefile.in b/tests/data/Makefile.in +index 2256422..e73ca96 100644 +--- a/tests/data/Makefile.in ++++ b/tests/data/Makefile.in +@@ -358,7 +358,7 @@ test1387 test1388 test1389 test1390 test1391 test1392 test1393 \ + test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \ + test1408 test1409 test1410 test1411 test1412 test1413 test1415 \ + test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ +-test1508 \ ++test1508 test1529 \ + test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \ + test2008 test2009 test2010 test2011 test2012 test2013 test2014 test2015 \ + test2016 test2017 test2018 test2019 test2020 test2021 test2022 \ +diff --git a/tests/data/test1529 b/tests/data/test1529 +new file mode 100644 +index 0000000..33df268 +--- /dev/null ++++ b/tests/data/test1529 +@@ -0,0 +1,43 @@ ++ ++ ++ ++HTTP ++HTTP GET ++HTTP proxy ++ ++ ++ ++# Server-side ++ ++ ++HTTP/1.1 200 OK ++We-are: good ++ ++ ++ ++ ++# Client-side ++ ++ ++http ++http-proxy ++ ++ ++lib1529 ++ ++ ++HTTP request-injection in URL sent over proxy ++ ++ ++ "http://the.old.moo:%HTTPPORT/1529" %HOSTIP:%PROXYPORT ++ ++ ++ ++# it should be detected and an error should be reported ++ ++# 3 == CURLE_URL_MALFORMAT ++ ++3 ++ ++ ++ +diff --git a/tests/libtest/Makefile.in b/tests/libtest/Makefile.in +index ed4d69f..124a276 100644 +--- a/tests/libtest/Makefile.in ++++ b/tests/libtest/Makefile.in +@@ -86,7 +86,7 @@ noinst_PROGRAMS = chkhostname$(EXEEXT) libauthretry$(EXEEXT) \ + lib599$(EXEEXT) lib1500$(EXEEXT) lib1501$(EXEEXT) \ + lib1502$(EXEEXT) lib1503$(EXEEXT) lib1504$(EXEEXT) \ + lib1505$(EXEEXT) lib1506$(EXEEXT) lib1507$(EXEEXT) \ +- lib1508$(EXEEXT) ++ lib1508$(EXEEXT) lib1529$(EXEEXT) + subdir = tests/libtest + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 + am__aclocal_m4_deps = $(top_srcdir)/m4/curl-compilers.m4 \ +@@ -188,6 +188,13 @@ am_lib1508_OBJECTS = lib1508-lib1508.$(OBJEXT) $(am__objects_151) \ + $(am__objects_152) $(am__objects_153) + lib1508_OBJECTS = $(am_lib1508_OBJECTS) + lib1508_DEPENDENCIES = $(am__DEPENDENCIES_1) ++am__objects_X60 = lib1529-first.$(OBJEXT) ++am__objects_X61 = lib1529-testutil.$(OBJEXT) ++am__objects_X62 = ../../lib/lib1529-warnless.$(OBJEXT) ++am_lib1529_OBJECTS = lib1529-lib1529.$(OBJEXT) $(am__objects_X60) \ ++ $(am__objects_X61) $(am__objects_X62) ++lib1529_OBJECTS = $(am_lib1529_OBJECTS) ++lib1529_DEPENDENCIES = $(am__DEPENDENCIES_1) + am__objects_21 = lib500-first.$(OBJEXT) + am__objects_22 = lib500-testutil.$(OBJEXT) + am__objects_23 = lib500-testtrace.$(OBJEXT) +@@ -648,6 +655,7 @@ SOURCES = $(libhostname_la_SOURCES) $(chkhostname_SOURCES) \ + $(lib1500_SOURCES) $(lib1501_SOURCES) $(lib1502_SOURCES) \ + $(lib1503_SOURCES) $(lib1504_SOURCES) $(lib1505_SOURCES) \ + $(lib1506_SOURCES) $(lib1507_SOURCES) $(lib1508_SOURCES) \ ++ $(lib1529_SOURCES) \ + $(lib500_SOURCES) $(lib501_SOURCES) \ + $(lib502_SOURCES) $(lib503_SOURCES) $(lib504_SOURCES) \ + $(lib505_SOURCES) $(lib506_SOURCES) $(lib507_SOURCES) \ +@@ -679,6 +687,7 @@ DIST_SOURCES = $(libhostname_la_SOURCES) $(chkhostname_SOURCES) \ + $(lib1500_SOURCES) $(lib1501_SOURCES) $(lib1502_SOURCES) \ + $(lib1503_SOURCES) $(lib1504_SOURCES) $(lib1505_SOURCES) \ + $(lib1506_SOURCES) $(lib1507_SOURCES) $(lib1508_SOURCES) \ ++ $(lib1529_SOURCES) \ + $(lib500_SOURCES) $(lib501_SOURCES) \ + $(lib502_SOURCES) $(lib503_SOURCES) $(lib504_SOURCES) \ + $(lib505_SOURCES) $(lib506_SOURCES) $(lib507_SOURCES) \ +@@ -1178,6 +1187,9 @@ lib1507_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1507 + lib1508_SOURCES = lib1508.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) + lib1508_LDADD = $(TESTUTIL_LIBS) + lib1508_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1508 ++lib1529_SOURCES = lib1529.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) ++lib1529_LDADD = $(TESTUTIL_LIBS) ++lib1529_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1529 + @BUILD_LIBHOSTNAME_FALSE@noinst_LTLIBRARIES = + + # Makefile.inc provides the source defines (TESTUTIL, SUPPORTFILES, +@@ -1282,6 +1294,9 @@ lib1507$(EXEEXT): $(lib1507_OBJECTS) $(lib1507_DEPENDENCIES) $(EXTRA_lib1507_DEP + lib1508$(EXEEXT): $(lib1508_OBJECTS) $(lib1508_DEPENDENCIES) $(EXTRA_lib1508_DEPENDENCIES) + @rm -f lib1508$(EXEEXT) + $(LINK) $(lib1508_OBJECTS) $(lib1508_LDADD) $(LIBS) ++lib1529$(EXEEXT): $(lib1529_OBJECTS) $(lib1529_DEPENDENCIES) $(EXTRA_lib1529_DEPENDENCIES) ++ @rm -f lib1529$(EXEEXT) ++ $(LINK) $(lib1529_OBJECTS) $(lib1529_LDADD) $(LIBS) + lib500$(EXEEXT): $(lib500_OBJECTS) $(lib500_DEPENDENCIES) $(EXTRA_lib500_DEPENDENCIES) + @rm -f lib500$(EXEEXT) + $(LINK) $(lib500_OBJECTS) $(lib500_LDADD) $(LIBS) +@@ -1557,6 +1572,10 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1508-lib1508.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1508-testutil.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1508-warnless.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1529-first.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1529-lib1529.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1529-testutil.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1529-warnless.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib500-first.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib500-lib500.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib500-testtrace.Po@am__quote@ +@@ -2312,6 +2331,62 @@ lib1508-warnless.obj: ../../lib/warnless.c + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1508_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1508-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi` + ++lib1529-lib1529.o: lib1529.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1529-lib1529.o -MD -MP -MF $(DEPDIR)/lib1529-lib1529.Tpo -c -o lib1529-lib1529.o `test -f 'lib1529.c' || echo '$(srcdir)/'`lib1529.c ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib1529-lib1529.Tpo $(DEPDIR)/lib1529-lib1529.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib1529.c' object='lib1529-lib1529.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1529-lib1529.o `test -f 'lib1529.c' || echo '$(srcdir)/'`lib1529.c ++ ++lib1529-lib1529.obj: lib1529.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1529-lib1529.obj -MD -MP -MF $(DEPDIR)/lib1529-lib1529.Tpo -c -o lib1529-lib1529.obj `if test -f 'lib1529.c'; then $(CYGPATH_W) 'lib1529.c'; else $(CYGPATH_W) '$(srcdir)/lib1529.c'; fi` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib1529-lib1529.Tpo $(DEPDIR)/lib1529-lib1529.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib1529.c' object='lib1529-lib1529.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1529-lib1529.obj `if test -f 'lib1529.c'; then $(CYGPATH_W) 'lib1529.c'; else $(CYGPATH_W) '$(srcdir)/lib1529.c'; fi` ++ ++lib1529-first.o: first.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1529-first.o -MD -MP -MF $(DEPDIR)/lib1529-first.Tpo -c -o lib1529-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib1529-first.Tpo $(DEPDIR)/lib1529-first.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='first.c' object='lib1529-first.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1529-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c ++ ++lib1529-first.obj: first.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1529-first.obj -MD -MP -MF $(DEPDIR)/lib1529-first.Tpo -c -o lib1529-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib1529-first.Tpo $(DEPDIR)/lib1529-first.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='first.c' object='lib1529-first.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1529-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi` ++ ++lib1529-testutil.o: testutil.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1529-testutil.o -MD -MP -MF $(DEPDIR)/lib1529-testutil.Tpo -c -o lib1529-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib1529-testutil.Tpo $(DEPDIR)/lib1529-testutil.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testutil.c' object='lib1529-testutil.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1529-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c ++ ++lib1529-testutil.obj: testutil.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1529-testutil.obj -MD -MP -MF $(DEPDIR)/lib1529-testutil.Tpo -c -o lib1529-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib1529-testutil.Tpo $(DEPDIR)/lib1529-testutil.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='testutil.c' object='lib1529-testutil.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1529-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi` ++ ++../../lib/lib1529-warnless.o: ../../lib/warnless.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1529-warnless.o -MD -MP -MF ../../lib/$(DEPDIR)/lib1529-warnless.Tpo -c -o ../../lib/lib1529-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1529-warnless.Tpo ../../lib/$(DEPDIR)/lib1529-warnless.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1529-warnless.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1529-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c ++ ++../../lib/lib1529-warnless.obj: ../../lib/warnless.c ++@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ../../lib/lib1529-warnless.obj -MD -MP -MF ../../lib/$(DEPDIR)/lib1529-warnless.Tpo -c -o ../../lib/lib1529-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi` ++@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ../../lib/$(DEPDIR)/lib1529-warnless.Tpo ../../lib/$(DEPDIR)/lib1529-warnless.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../../lib/warnless.c' object='../../lib/lib1529-warnless.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1529_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ../../lib/lib1529-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi` ++ + lib500-lib500.o: lib500.c + @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib500_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib500-lib500.o -MD -MP -MF $(DEPDIR)/lib500-lib500.Tpo -c -o lib500-lib500.o `test -f 'lib500.c' || echo '$(srcdir)/'`lib500.c + @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib500-lib500.Tpo $(DEPDIR)/lib500-lib500.Po +diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc +index bf73036..4f3ef6f 100644 +--- a/tests/libtest/Makefile.inc ++++ b/tests/libtest/Makefile.inc +@@ -23,7 +23,8 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \ + lib582 lib583 lib585 lib586 lib587 \ + lib590 lib591 lib597 lib598 lib599 \ + \ +- lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 ++ lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 \ ++ lib1529 + + chkhostname_SOURCES = chkhostname.c ../../lib/curl_gethostname.c + chkhostname_LDADD = @CURL_NETWORK_LIBS@ +@@ -320,3 +321,7 @@ lib1507_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1507 + lib1508_SOURCES = lib1508.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) + lib1508_LDADD = $(TESTUTIL_LIBS) + lib1508_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1508 ++ ++lib1529_SOURCES = lib1529.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) ++lib1529_LDADD = $(TESTUTIL_LIBS) ++lib1529_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1529 +diff --git a/tests/libtest/lib1529.c b/tests/libtest/lib1529.c +new file mode 100644 +index 0000000..3def142 +--- /dev/null ++++ b/tests/libtest/lib1529.c +@@ -0,0 +1,59 @@ ++/*************************************************************************** ++ * _ _ ____ _ ++ * Project ___| | | | _ \| | ++ * / __| | | | |_) | | ++ * | (__| |_| | _ <| |___ ++ * \___|\___/|_| \_\_____| ++ * ++ * Copyright (C) 1998 - 2014, 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 http://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. ++ * ++ ***************************************************************************/ ++ ++#include "test.h" ++ ++#include "memdebug.h" ++ ++int test(char *URL) ++{ ++ CURL *curl = NULL; ++ CURLcode res = CURLE_FAILED_INIT; ++ char bURL[512]; ++ snprintf(bURL, sizeof(bURL), "%s HTTP/1.1\r\nGET http://1529.com/1529", URL); ++ ++ if(curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { ++ fprintf(stderr, "curl_global_init() failed\n"); ++ return TEST_ERR_MAJOR_BAD; ++ } ++ ++ if((curl = curl_easy_init()) == NULL) { ++ fprintf(stderr, "curl_easy_init() failed\n"); ++ curl_global_cleanup(); ++ return TEST_ERR_MAJOR_BAD; ++ } ++ ++ test_setopt(curl, CURLOPT_URL, bURL); ++ test_setopt(curl, CURLOPT_PROXY, libtest_arg2); ++ test_setopt(curl, CURLOPT_VERBOSE, 1L); ++ test_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); ++ test_setopt(curl, CURLOPT_HEADER, 1L); ++ ++ res = curl_easy_perform(curl); ++ ++test_cleanup: ++ ++ curl_easy_cleanup(curl); ++ curl_global_cleanup(); ++ ++ return (int)res; ++} +-- +2.1.0 + diff --git a/SOURCES/0031-curl-7.29.0-CVE-2015-3143.patch b/SOURCES/0031-curl-7.29.0-CVE-2015-3143.patch new file mode 100644 index 0000000..7b2e2a5 --- /dev/null +++ b/SOURCES/0031-curl-7.29.0-CVE-2015-3143.patch @@ -0,0 +1,33 @@ +From a4c6f86f94e7b86026770e8b9da034daf514e5bc Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 16 Apr 2015 13:26:46 +0200 +Subject: [PATCH] ConnectionExists: for NTLM re-use, require credentials to + match + +CVE-2015-3143 + +Bug: http://curl.haxx.se/docs/adv_20150422A.html +Reported-by: Paras Sethia + +Upstream-commit: 31be461c6b659312100c47be6ddd5f0f569290f6 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/url.c b/lib/url.c +index 22e3856..2dc56ae 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -2973,7 +2973,7 @@ ConnectionExists(struct SessionHandle *data, + } + } + if((!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) || +- ((needle->handler->protocol & CURLPROTO_HTTP) && wantNTLM)) { ++ (wantNTLM || check->ntlm.state != NTLMSTATE_NONE)) { + /* This protocol requires credentials per connection or is HTTP+NTLM, + so verify that we're using the same name and password as well */ + if(!strequal(needle->user, check->user) || +-- +2.3.6 + diff --git a/SOURCES/0032-curl-7.29.0-CVE-2015-3148.patch b/SOURCES/0032-curl-7.29.0-CVE-2015-3148.patch new file mode 100644 index 0000000..55883d9 --- /dev/null +++ b/SOURCES/0032-curl-7.29.0-CVE-2015-3148.patch @@ -0,0 +1,108 @@ +From 55689681595d76ee53d76d6698f5a99e18395857 Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Fri, 11 Jul 2014 11:09:34 +0100 +Subject: [PATCH 1/2] Don't clear GSSAPI state between each exchange in the + negotiation + +GSSAPI doesn't work very well if we forget everything ever time. + +XX: Is Curl_http_done() the right place to do the final cleanup? + +Upstream-commit: f78ae415d24b9bd89d6c121c556e411fdb21c6aa +Signed-off-by: Kamil Dudka +--- + lib/http.c | 6 ++++++ + lib/http_negotiate.c | 1 - + lib/http_negotiate_sspi.c | 1 - + 3 files changed, 6 insertions(+), 2 deletions(-) + +diff --git a/lib/http.c b/lib/http.c +index e2448bc..c32eae0 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1404,6 +1404,12 @@ CURLcode Curl_http_done(struct connectdata *conn, + + Curl_unencode_cleanup(conn); + ++#ifdef USE_HTTP_NEGOTIATE ++ if(data->state.proxyneg.state == GSS_AUTHSENT || ++ data->state.negotiate.state == GSS_AUTHSENT) ++ Curl_cleanup_negotiate(data); ++#endif ++ + /* set the proper values (possibly modified on POST) */ + conn->fread_func = data->set.fread_func; /* restore */ + conn->fread_in = data->set.in; /* restore */ +diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c +index 535a427..b56e7d0 100644 +--- a/lib/http_negotiate.c ++++ b/lib/http_negotiate.c +@@ -343,7 +343,6 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) + else + conn->allocptr.userpwd = userp; + free(encoded); +- Curl_cleanup_negotiate (conn->data); + return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; + } + +diff --git a/lib/http_negotiate_sspi.c b/lib/http_negotiate_sspi.c +index 1381d52..678e605 100644 +--- a/lib/http_negotiate_sspi.c ++++ b/lib/http_negotiate_sspi.c +@@ -271,7 +271,6 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy) + else + conn->allocptr.userpwd = userp; + free(encoded); +- Curl_cleanup_negotiate (conn->data); + return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK; + } + +-- +2.3.6 + + +From 28e84254779c0d4b31844d928e5dae8941128f05 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 18 Apr 2015 23:50:16 +0200 +Subject: [PATCH 2/2] http_done: close Negotiate connections when done + +When doing HTTP requests Negotiate authenticated, the entire connnection +may become authenticated and not just the specific HTTP request which is +otherwise how HTTP works, as Negotiate can basically use NTLM under the +hood. curl was not adhering to this fact but would assume that such +requests would also be authenticated per request. + +CVE-2015-3148 + +Bug: http://curl.haxx.se/docs/adv_20150422B.html +Reported-by: Isaac Boukris + +Upstream-commit: 79b9d5f1a42578f807a6c94914bc65cbaa304b6d +Signed-off-by: Kamil Dudka +--- + lib/http.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/lib/http.c b/lib/http.c +index c32eae0..04beeb1 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1406,8 +1406,14 @@ CURLcode Curl_http_done(struct connectdata *conn, + + #ifdef USE_HTTP_NEGOTIATE + if(data->state.proxyneg.state == GSS_AUTHSENT || +- data->state.negotiate.state == GSS_AUTHSENT) ++ data->state.negotiate.state == GSS_AUTHSENT) { ++ /* add forbid re-use if http-code != 401/407 as a WA only needed for ++ * 401/407 that signal auth failure (empty) otherwise state will be RECV ++ * with current code */ ++ if((data->req.httpcode != 401) && (data->req.httpcode != 407)) ++ conn->bits.close = TRUE; /* Negotiate transfer completed */ + Curl_cleanup_negotiate(data); ++ } + #endif + + /* set the proper values (possibly modified on POST) */ +-- +2.3.6 + diff --git a/SOURCES/0033-curl-7.29.0-29bf0598.patch b/SOURCES/0033-curl-7.29.0-29bf0598.patch new file mode 100644 index 0000000..4d34cea --- /dev/null +++ b/SOURCES/0033-curl-7.29.0-29bf0598.patch @@ -0,0 +1,281 @@ +From f9ebe8047f5f62dfcee379b010d8207f0d6985b1 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 3 Jun 2013 20:19:51 +0200 +Subject: [PATCH 1/5] curl_multi_wait: reduce timeout if the multi handle wants + to + +If the multi handle's pending timeout is less than what is passed into +this function, it will now opt to use the shorter time anyway since it +is a very good hint that the handle wants to process something in a +shorter time than what otherwise would happen. + +curl_multi_wait.3 was updated accordingly to clarify + +This is the reason for bug #1224 + +Bug: http://curl.haxx.se/bug/view.cgi?id=1224 +Reported-by: Andrii Moiseiev + +Upstream-commit: 29bf0598aad58d9da5dd8c5358f5175dae49026d +Signed-off-by: Kamil Dudka +--- + docs/libcurl/curl_multi_wait.3 | 3 +++ + lib/multi.c | 9 +++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/docs/libcurl/curl_multi_wait.3 b/docs/libcurl/curl_multi_wait.3 +index b14760b..57c40f0 100644 +--- a/docs/libcurl/curl_multi_wait.3 ++++ b/docs/libcurl/curl_multi_wait.3 +@@ -36,6 +36,9 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, + This function polls on all file descriptors used by the curl easy handles + contained in the given multi handle set. It will block until activity is + detected on at least one of the handles or \fItimeout_ms\fP has passed. ++Alternatively, if the multi handle has a pending internal timeout that has a ++shorter expiry time than \fItimeout_ms\fP, that shorter time will be used ++instead to make sure timeout accuracy is reasonably kept. + + The calling application may pass additional curl_waitfd structures which are + similar to \fIpoll(2)\fP's pollfd structure to be waited on in the same call. +diff --git a/lib/multi.c b/lib/multi.c +index 9a8e68e..c8dd97d 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -81,6 +81,8 @@ static bool isHandleAtHead(struct SessionHandle *handle, + static CURLMcode add_next_timeout(struct timeval now, + struct Curl_multi *multi, + struct SessionHandle *d); ++static CURLMcode multi_timeout(struct Curl_multi *multi, ++ long *timeout_ms); + + #ifdef DEBUGBUILD + static const char * const statename[]={ +@@ -804,10 +806,17 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, + unsigned int i; + unsigned int nfds = extra_nfds; + struct pollfd *ufds = NULL; ++ long timeout_internal; + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + ++ /* If the internally desired timeout is actually shorter than requested from ++ the outside, then use the shorter time! */ ++ (void)multi_timeout(multi, &timeout_internal); ++ if(timeout_internal < (long)timeout_ms) ++ timeout_ms = (int)timeout_internal; ++ + /* Count up how many fds we have from the multi handle */ + easy=multi->easy.next; + while(easy != &multi->easy) { +-- +2.4.0 + + +From 3db7d3959815224b7a618860be783fed44fab72a Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 4 Jun 2013 13:22:40 +0200 +Subject: [PATCH 2/5] curl_multi_wait: only use internal timer if not -1 + +commit 29bf0598aad5 introduced a problem when the "internal" timeout is +prefered to the given if shorter, as it didn't consider the case where +-1 was returned. Now the internal timeout is only considered if not -1. + +Reported-by: Tor Arntsen +Bug: http://curl.haxx.se/mail/lib-2013-06/0015.html + +Upstream-commit: 0bf5ce77aabe7307e41db13a0d03a63517fdc366 +Signed-off-by: Kamil Dudka +--- + lib/multi.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/lib/multi.c b/lib/multi.c +index c8dd97d..6dfce9b 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -812,9 +812,10 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, + return CURLM_BAD_HANDLE; + + /* If the internally desired timeout is actually shorter than requested from +- the outside, then use the shorter time! */ ++ the outside, then use the shorter time! But only if the internal timer ++ is actually larger than 0! */ + (void)multi_timeout(multi, &timeout_internal); +- if(timeout_internal < (long)timeout_ms) ++ if((timeout_internal > 0) && (timeout_internal < (long)timeout_ms)) + timeout_ms = (int)timeout_internal; + + /* Count up how many fds we have from the multi handle */ +-- +2.4.0 + + +From 761d88bb94e33a119f8e10083c33acf6fe216c79 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 20 Aug 2013 22:45:47 +0200 +Subject: [PATCH 3/5] FTP: fix getsock during DO_MORE state + +... when doing upload it would return the wrong values at times. This +commit attempts to cleanup the mess. + +Bug: http://curl.haxx.se/mail/lib-2013-08/0109.html +Reported-by: Mike Mio + +Upstream-commit: c4a7ca038e26a57df952b4ea560f9b718a5ebd1d +Signed-off-by: Kamil Dudka +--- + lib/ftp.c | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +diff --git a/lib/ftp.c b/lib/ftp.c +index 4501116..63d1e64 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -877,14 +877,9 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, + return GETSOCK_BLANK; + + /* When in DO_MORE state, we could be either waiting for us to connect to a +- remote site, or we could wait for that site to connect to us. Or just +- handle ordinary commands. +- +- When waiting for a connect, we will be in FTP_STOP state and then we wait +- for the secondary socket to become writeable. If we're in another state, +- we're still handling commands on the control (primary) connection. +- +- */ ++ * remote site, or we could wait for that site to connect to us. Or just ++ * handle ordinary commands. ++ */ + + switch(ftpc->state) { + case FTP_STOP: +@@ -893,13 +888,12 @@ static int ftp_domore_getsock(struct connectdata *conn, curl_socket_t *socks, + return Curl_pp_getsock(&conn->proto.ftpc.pp, socks, numsocks); + } + +- socks[0] = conn->sock[SECONDARYSOCKET]; +- if(ftpc->wait_data_conn) { +- socks[1] = conn->sock[FIRSTSOCKET]; +- return GETSOCK_READSOCK(0) | GETSOCK_READSOCK(1); +- } ++ /* if stopped and still in this state, then we're also waiting for a ++ connect on the secondary connection */ ++ socks[0] = conn->sock[FIRSTSOCKET]; ++ socks[1] = conn->sock[SECONDARYSOCKET]; + +- return GETSOCK_READSOCK(0); ++ return GETSOCK_READSOCK(FIRSTSOCKET) | GETSOCK_WRITESOCK(SECONDARYSOCKET); + } + + /* This is called after the FTP_QUOTE state is passed. +@@ -2421,6 +2415,8 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn, + if(data->set.ftp_use_port) { + bool connected; + ++ state(conn, FTP_STOP); /* no longer in STOR state */ ++ + result = AllowServerConnect(conn, &connected); + if(result) + return result; +-- +2.4.0 + + +From 5b18b86746cf09208e57adb69edcf411b10f5e30 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 6 Apr 2013 17:49:58 +0200 +Subject: [PATCH 4/5] ftp tests: libcurl returns CURLE_FTP_ACCEPT_FAILED better + now + +Since commit 57aeabcc1a20f, it handles errors on the control connection +while waiting for the data connection better. + +Test 591 and 592 are updated accordingly. + +Upstream-commit: 18f0ab7bd353289049ca06c4a7105473e37a8f20 +Signed-off-by: Kamil Dudka +--- + tests/data/test591 | 4 ++-- + tests/data/test592 | 5 +++-- + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/tests/data/test591 b/tests/data/test591 +index 42a2271..1455a38 100644 +--- a/tests/data/test591 ++++ b/tests/data/test591 +@@ -63,9 +63,9 @@ TYPE I + STOR 591 + QUIT + +-# CURLE_UPLOAD_FAILED = 25 ++# CURLE_FTP_ACCEPT_FAILED = 10 + +-25 ++10 + + + +diff --git a/tests/data/test592 b/tests/data/test592 +index 23aa6c4..f443205 100644 +--- a/tests/data/test592 ++++ b/tests/data/test592 +@@ -62,10 +62,11 @@ EPRT |1| + PORT + TYPE I + STOR 592 ++QUIT + +-# 28 == CURLE_OPERATION_TIMEDOUT ++# CURLE_FTP_ACCEPT_FAILED = 10 + +-28 ++10 + + + +-- +2.4.0 + + +From 599ef7d7ec8ed7a979df1cd3180819359e6af97f Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 6 Jun 2013 22:20:39 +0200 +Subject: [PATCH 5/5] lib1500: remove bad check + +After curl_multi_wait() returns, this test checked that we got exactly +one file descriptor told to read from, but we cannot be sure that is +true. curl_multi_wait() will sometimes return earlier without any file +descriptor to handle, just just because it is a suitable time to call +*perform(). + +This problem showed up with commit 29bf0598. + +Bug: http://curl.haxx.se/mail/lib-2013-06/0029.html +Reported-by: Fabian Keil + +Upstream-commit: 87cf677eca55abee88f0a9dced9e6fa570143873 +Signed-off-by: Kamil Dudka +--- + tests/libtest/lib1500.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/tests/libtest/lib1500.c b/tests/libtest/lib1500.c +index 784bdb2..736a817 100644 +--- a/tests/libtest/lib1500.c ++++ b/tests/libtest/lib1500.c +@@ -61,11 +61,6 @@ int test(char *URL) + res = -1; + goto test_cleanup; + } +- if (num != 1) { +- printf("curl_multi_wait() returned on %d handle(s), expected 1\n", num); +- res = -1; +- goto test_cleanup; +- } + + abort_on_test_timeout(); + +-- +2.4.0 + diff --git a/SOURCES/0103-curl-7.29.0-default-tls-version.patch b/SOURCES/0103-curl-7.29.0-default-tls-version.patch new file mode 100644 index 0000000..259fd5f --- /dev/null +++ b/SOURCES/0103-curl-7.29.0-default-tls-version.patch @@ -0,0 +1,42 @@ +From ebe7a9186469a5901a91469d107851abfdaa3993 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Tue, 5 May 2015 18:59:59 +0200 +Subject: [PATCH] nss: use the default min/max TLS version provided by NSS + +--- + lib/nss.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 0691394..6b7c309 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1206,7 +1206,7 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver, + switch (data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: +- return CURLE_OK; ++ break; + + case CURL_SSLVERSION_TLSv1: + sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; +@@ -1368,10 +1368,12 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) + goto error; + + /* enable/disable the requested SSL version(s) */ +- if(nss_init_sslver(&sslver, data) != CURLE_OK) +- goto error; +- if(SSL_VersionRangeSet(model, &sslver) != SECSuccess) +- goto error; ++ if(data->set.ssl.version != CURL_SSLVERSION_DEFAULT) { ++ if(nss_init_sslver(&sslver, data) != CURLE_OK) ++ goto error; ++ if(SSL_VersionRangeSet(model, &sslver) != SECSuccess) ++ goto error; ++ } + + ssl_cbc_random_iv = !data->set.ssl_enable_beast; + #ifdef SSL_CBC_RANDOM_IV +-- +2.4.0 + diff --git a/SPECS/curl.spec b/SPECS/curl.spec index e7c93e2..34022fd 100644 --- a/SPECS/curl.spec +++ b/SPECS/curl.spec @@ -1,7 +1,7 @@ Summary: A utility for getting files from remote servers (FTP, HTTP, and others) Name: curl Version: 7.29.0 -Release: 19%{?dist} +Release: 25%{?dist} License: MIT Group: Applications/Internet Source: http://curl.haxx.se/download/%{name}-%{version}.tar.lzma @@ -62,7 +62,49 @@ Patch17: 0017-curl-7.29.0-ffb8a21d.patch Patch18: 0018-curl-7.29.0-03c28820.patch # fix connection re-use when using different log-in credentials (CVE-2014-0138) -Patch19: 0018-curl-7.29.0-517b06d6.patch +Patch19: 0019-curl-7.29.0-517b06d6.patch + +# eliminate unnecessary delay when resolving host from /etc/hosts (#1130239) +Patch20: 0020-curl-7.29.0-d529f388.patch + +# allow to enable/disable new AES cipher-suites (#1066065) +Patch21: 0021-curl-7.29.0-67061e3f.patch + +# call PR_Cleanup() on curl tool exit if NSPR is used (#1071254) +Patch22: 0022-curl-7.29.0-24c3cdce.patch + +# implement non-blocking TLS handshake (#1091429) +Patch23: 0023-curl-7.29.0-8868a226.patch + +# fix limited connection re-use for unencrypted HTTP (#1101092) +Patch24: 0024-curl-7.29.0-68f0166a.patch + +# disable libcurl-level downgrade to SSLv3 (#1154060) +Patch25: 0025-curl-7.29.0-3f430c9c.patch + +# include response headers added by proxy in CURLINFO_HEADER_SIZE (#1161182) +Patch26: 0026-curl-7.29.0-bc6037ed.patch + +# ignore CURLOPT_FORBID_REUSE during NTLM HTTP auth (#1166264) +Patch27: 0027-curl-7.29.0-63a0bd42.patch + +# use only full matches for hosts used as IP address in cookies (CVE-2014-3613) +Patch28: 0028-curl-7.29.0-CVE-2014-3613.patch + +# fix handling of CURLOPT_COPYPOSTFIELDS in curl_easy_duphandle (CVE-2014-3707) +Patch29: 0029-curl-7.29.0-CVE-2014-3707.patch + +# reject CRLFs in URLs passed to proxy (CVE-2014-8150) +Patch30: 0030-curl-7.29.0-CVE-2014-8150.patch + +# require credentials to match for NTLM re-use (CVE-2015-3143) +Patch31: 0031-curl-7.29.0-CVE-2015-3143.patch + +# close Negotiate connections when done (CVE-2015-3148) +Patch32: 0032-curl-7.29.0-CVE-2015-3148.patch + +# improve handling of timeouts and blocking direction to speed up FTP (#1218272) +Patch33: 0033-curl-7.29.0-29bf0598.patch # patch making libcurl multilib ready Patch101: 0101-curl-7.29.0-multilib.patch @@ -70,6 +112,9 @@ Patch101: 0101-curl-7.29.0-multilib.patch # prevent configure script from discarding -g in CFLAGS (#496778) Patch102: 0102-curl-7.29.0-debug.patch +# use the default min/max TLS version provided by NSS (#1170339) +Patch103: 0103-curl-7.29.0-default-tls-version.patch + # use localhost6 instead of ip6-localhost in the curl test-suite Patch104: 0104-curl-7.19.7-localhost6.patch @@ -195,10 +240,25 @@ documentation of the library, too. %patch18 -p1 %patch105 -p1 %patch19 -p1 - -# Fedora patches +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 +%patch25 -p1 +%patch26 -p1 +%patch27 -p1 +%patch28 -p1 +%patch29 -p1 +%patch30 -p1 +%patch31 -p1 +%patch32 -p1 +%patch33 -p1 + +# Fedora/RHEL patches %patch101 -p1 %patch102 -p1 +%patch103 -p1 %patch104 -p1 %patch106 -p1 %patch107 -p1 @@ -312,6 +372,34 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/aclocal/libcurl.m4 %changelog +* Mon May 11 2015 Kamil Dudka 7.29.0-25 +- fix spurious failure of test 1500 on ppc64le (#1218272) + +* Tue May 05 2015 Kamil Dudka 7.29.0-24 +- use the default min/max TLS version provided by NSS (#1170339) +- improve handling of timeouts and blocking direction to speed up FTP (#1218272) + +* Mon Apr 27 2015 Kamil Dudka 7.29.0-23 +- require credentials to match for NTLM re-use (CVE-2015-3143) +- close Negotiate connections when done (CVE-2015-3148) + +* Thu Jan 08 2015 Kamil Dudka 7.29.0-22 +- reject CRLFs in URLs passed to proxy (CVE-2014-8150) + +* Thu Dec 18 2014 Kamil Dudka 7.29.0-21 +- use only full matches for hosts used as IP address in cookies (CVE-2014-3613) +- fix handling of CURLOPT_COPYPOSTFIELDS in curl_easy_duphandle (CVE-2014-3707) + +* Thu Nov 27 2014 Kamil Dudka 7.29.0-20 +- eliminate unnecessary delay when resolving host from /etc/hosts (#1130239) +- allow to enable/disable new AES cipher-suites (#1066065) +- call PR_Cleanup() on curl tool exit if NSPR is used (#1071254) +- implement non-blocking TLS handshake (#1091429) +- fix limited connection re-use for unencrypted HTTP (#1101092) +- disable libcurl-level downgrade to SSLv3 (#1154060) +- include response headers added by proxy in CURLINFO_HEADER_SIZE (#1161182) +- ignore CURLOPT_FORBID_REUSE during NTLM HTTP auth (#1166264) + * Wed Mar 26 2014 Kamil Dudka 7.29.0-19 - fix connection re-use when using different log-in credentials (CVE-2014-0138)