From a2d4e12f88c04a989da604ad73752f7f8c70b6ad Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 01 2017 03:21:34 +0000 Subject: import curl-7.29.0-42.el7 --- diff --git a/SOURCES/0019-curl-7.29.0-517b06d6.patch b/SOURCES/0019-curl-7.29.0-517b06d6.patch index b56875e..777e8b8 100644 --- a/SOURCES/0019-curl-7.29.0-517b06d6.patch +++ b/SOURCES/0019-curl-7.29.0-517b06d6.patch @@ -45,7 +45,7 @@ index 9690dfa..0174ff4 100644 ((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, ++ /* This proto 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)) { diff --git a/SOURCES/0028-curl-7.29.0-CVE-2014-3613.patch b/SOURCES/0028-curl-7.29.0-CVE-2014-3613.patch index f1973f1..6ccba89 100644 --- a/SOURCES/0028-curl-7.29.0-CVE-2014-3613.patch +++ b/SOURCES/0028-curl-7.29.0-CVE-2014-3613.patch @@ -1254,7 +1254,7 @@ index d4fe9a3..956efd4 100644 - 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))) { diff --git a/SOURCES/0031-curl-7.29.0-CVE-2015-3143.patch b/SOURCES/0031-curl-7.29.0-CVE-2015-3143.patch index 7b2e2a5..c69af4a 100644 --- a/SOURCES/0031-curl-7.29.0-CVE-2015-3143.patch +++ b/SOURCES/0031-curl-7.29.0-CVE-2015-3143.patch @@ -25,7 +25,7 @@ index 22e3856..2dc56ae 100644 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, + /* This proto 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) || -- diff --git a/SOURCES/0044-curl-7.29.0-CVE-2016-7167.patch b/SOURCES/0044-curl-7.29.0-CVE-2016-7167.patch new file mode 100644 index 0000000..5130556 --- /dev/null +++ b/SOURCES/0044-curl-7.29.0-CVE-2016-7167.patch @@ -0,0 +1,94 @@ +From 7959c5713bbec03c9284a14b1fdd7379520199bc Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 8 Sep 2016 22:59:54 +0200 +Subject: [PATCH 1/2] curl_easy_escape: deny negative string lengths as input + +CVE-2016-7167 + +Bug: https://curl.haxx.se/docs/adv_20160914.html + +Upstream-commit: 826a9ced2bed217155e34065ef4048931f327b1e +Signed-off-by: Kamil Dudka +--- + lib/escape.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/lib/escape.c b/lib/escape.c +index 40338a9..c6aa3b9 100644 +--- a/lib/escape.c ++++ b/lib/escape.c +@@ -80,15 +80,21 @@ char *curl_unescape(const char *string, int length) + + char *curl_easy_escape(CURL *handle, const char *string, int inlength) + { +- size_t alloc = (inlength?(size_t)inlength:strlen(string))+1; ++ size_t alloc; + char *ns; + char *testing_ptr = NULL; + unsigned char in; /* we need to treat the characters unsigned */ +- size_t newlen = alloc; ++ size_t newlen; + size_t strindex=0; + size_t length; + CURLcode res; + ++ if(inlength < 0) ++ return NULL; ++ ++ alloc = (inlength?(size_t)inlength:strlen(string))+1; ++ newlen = alloc; ++ + ns = malloc(alloc); + if(!ns) + return NULL; +-- +2.7.4 + + +From 6a280152e3893938e5d26f5d535613eefab80b5a Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 13 Sep 2016 23:00:50 +0200 +Subject: [PATCH 2/2] curl_easy_unescape: deny negative string lengths as input + +CVE-2016-7167 + +Bug: https://curl.haxx.se/docs/adv_20160914.html + +Upstream-commit: 01cf1308ee2e792c77bb1d2c9218c56a30fd40ae +Signed-off-by: Kamil Dudka +--- + lib/escape.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/lib/escape.c b/lib/escape.c +index c6aa3b9..808ac6c 100644 +--- a/lib/escape.c ++++ b/lib/escape.c +@@ -219,14 +219,16 @@ char *curl_easy_unescape(CURL *handle, const char *string, int length, + int *olen) + { + char *str = NULL; +- size_t inputlen = length; +- size_t outputlen; +- CURLcode res = Curl_urldecode(handle, string, inputlen, &str, &outputlen, +- FALSE); +- if(res) +- return NULL; +- if(olen) +- *olen = curlx_uztosi(outputlen); ++ if(length >= 0) { ++ size_t inputlen = length; ++ size_t outputlen; ++ CURLcode res = Curl_urldecode(handle, string, inputlen, &str, &outputlen, ++ FALSE); ++ if(res) ++ return NULL; ++ if(olen) ++ *olen = curlx_uztosi(outputlen); ++ } + return str; + } + +-- +2.7.4 + diff --git a/SOURCES/0045-curl-7.29.0-865d4138.patch b/SOURCES/0045-curl-7.29.0-865d4138.patch new file mode 100644 index 0000000..7d03298 --- /dev/null +++ b/SOURCES/0045-curl-7.29.0-865d4138.patch @@ -0,0 +1,859 @@ +From e0a1f91d29349d2ce45960f14ebe8e0fa043364e Mon Sep 17 00:00:00 2001 +From: Jared Jennings +Date: Fri, 5 Apr 2013 16:01:31 +0200 +Subject: [PATCH 01/10] curl -E: allow to escape ':' in cert nickname + +Upstream-commit: 865d4138a08daff460f116c2494adb9c889f5304 +Signed-off-by: Kamil Dudka +--- + src/tool_getparam.c | 123 ++++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 100 insertions(+), 23 deletions(-) + +diff --git a/src/tool_getparam.c b/src/tool_getparam.c +index 57cf97d..db29c0d 100644 +--- a/src/tool_getparam.c ++++ b/src/tool_getparam.c +@@ -290,6 +290,99 @@ static const struct feat feats[] = { + {"unix-sockets", CURL_VERSION_UNIX_SOCKETS} + }; + ++/* https://sourceforge.net/p/curl/bugs/1196/ */ ++static void parse_cert_parameter(const char *cert_parameter, ++ char **certname, ++ char **passphrase) ++{ ++ size_t param_length = strlen(cert_parameter); ++ size_t parsed_chars = 0; ++ size_t span; ++ const char *param_place = NULL; ++ char *certname_place = NULL; ++ /* most trivial assumption: cert_parameter is empty */ ++ if(param_length == 0) { ++ *certname = NULL; ++ *passphrase = NULL; ++ return; ++ } ++ /* next less trivial: cert_parameter contains no colon nor backslash; this ++ * means no passphrase was given and no characters escaped */ ++ if(!strpbrk(cert_parameter, ":\\")) { ++ *certname = strdup(cert_parameter); ++ *passphrase = NULL; ++ return; ++ } ++ /* deal with escaped chars; find unescaped colon if it exists */ ++ *certname = (char *) malloc(param_length + 1); ++ *passphrase = NULL; ++ param_place = cert_parameter; ++ certname_place = *certname; ++ param_place = cert_parameter; ++ while(*param_place) { ++ span = strcspn(param_place, ":\\"); ++ strncpy(certname_place, param_place, span); ++ param_place += span; ++ certname_place += span; ++ *certname_place = '\0'; ++ /* we just ate all the non-special chars. now we're on either a special ++ * char or the end of the string. */ ++ switch(*param_place) { ++ case '\0': ++ break; ++ case '\\': ++ param_place++; ++ switch(*param_place) { ++ case '\0': ++ *certname_place++ = '\\'; ++ break; ++ case '\\': ++ *certname_place++ = '\\'; ++ param_place++; ++ break; ++ case ':': ++ *certname_place++ = ':'; ++ param_place++; ++ break; ++ default: ++ *certname_place++ = '\\'; ++ *certname_place++ = *param_place; ++ param_place++; ++ break; ++ } ++ break; ++ case ':': ++ /* Since we live in a world of weirdness and confusion, the win32 ++ dudes can use : when using drive letters and thus c:\file:password ++ needs to work. In order not to break compatibility, we still use : as ++ separator, but we try to detect when it is used for a file name! On ++ windows. */ ++#ifdef WIN32 ++ if(param_place && ++ (param_place == &cert_parameter[1]) && ++ (cert_parameter[2] == '\\' || cert_parameter[2] == '/') && ++ (ISALPHA(cert_parameter[0])) ) { ++ /* colon in the second column, followed by a backslash, and the ++ first character is an alphabetic letter: ++ ++ this is a drive letter colon */ ++ *certname_place++ = ':'; ++ param_place++; ++ break; ++ } ++#endif ++ /* escaped colons and Windows drive letter colons were handled ++ * above; if we're still here, this is a separating colon */ ++ param_place++; ++ if(strlen(param_place) > 0) { ++ *passphrase = strdup(param_place); ++ } ++ return; ++ break; ++ } ++ } ++} ++ + ParameterError getparameter(char *flag, /* f or -long-flag */ + char *nextarg, /* NULL if unset */ + bool *usedarg, /* set to TRUE if the arg +@@ -1227,30 +1320,14 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ + break; + default: /* certificate file */ + { +- char *ptr = strchr(nextarg, ':'); +- /* Since we live in a world of weirdness and confusion, the win32 +- dudes can use : when using drive letters and thus +- c:\file:password needs to work. In order not to break +- compatibility, we still use : as separator, but we try to detect +- when it is used for a file name! On windows. */ +-#ifdef WIN32 +- if(ptr && +- (ptr == &nextarg[1]) && +- (nextarg[2] == '\\' || nextarg[2] == '/') && +- (ISALPHA(nextarg[0])) ) +- /* colon in the second column, followed by a backslash, and the +- first character is an alphabetic letter: +- +- this is a drive letter colon */ +- ptr = strchr(&nextarg[3], ':'); /* find the next one instead */ +-#endif +- if(ptr) { +- /* we have a password too */ +- *ptr = '\0'; +- ptr++; +- GetStr(&config->key_passwd, ptr); ++ char *certname, *passphrase; ++ parse_cert_parameter(nextarg, &certname, &passphrase); ++ if(certname) { ++ GetStr(&config->cert, certname); ++ } ++ if(passphrase) { ++ GetStr(&config->key_passwd, passphrase); + } +- GetStr(&config->cert, nextarg); + cleanarg(nextarg); + } + } +-- +2.7.4 + + +From 9a5f8a20402e549211d9df1d9ef0cb0b00e5ed8f Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 3 May 2013 23:12:00 +0200 +Subject: [PATCH 02/10] curl.1: document escape sequences recognized by -E + +Upstream-commit: 42e01cff9af12441eb60694af9c0c86817e8f7e0 +Signed-off-by: Kamil Dudka +--- + docs/curl.1 | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/docs/curl.1 b/docs/curl.1 +index ad26007..c9bb336 100644 +--- a/docs/curl.1 ++++ b/docs/curl.1 +@@ -397,7 +397,10 @@ curl the nickname of the certificate to use within the NSS database defined + by the environment variable SSL_DIR (or by default /etc/pki/nssdb). If the + NSS PEM PKCS#11 module (libnsspem.so) is available then PEM files may be + loaded. If you want to use a file from the current directory, please precede +-it with "./" prefix, in order to avoid confusion with a nickname. ++it with "./" prefix, in order to avoid confusion with a nickname. If the ++nickname contains ":", it needs to be preceded by "\\" so that it is not ++recognized as password delimiter. If the nickname contains "\\", it needs to ++be escaped as "\\\\" so that it is not recognized as an escape character. + + If this option is used several times, the last one will be used. + .IP "--engine " +-- +2.7.4 + + +From fcfd1f85946ed0784365c55cf6c7a196c328308a Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 5 Apr 2013 16:10:46 +0200 +Subject: [PATCH 03/10] tool_getparam: describe what parse_cert_parameter() + does + +... and de-duplicate the code initializing *passphrase + +Upstream-commit: a15b2b6c6204766ef391c1831fb4506635bab0a6 +Signed-off-by: Kamil Dudka +--- + src/tool_getparam.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/tool_getparam.c b/src/tool_getparam.c +index db29c0d..77d44c4 100644 +--- a/src/tool_getparam.c ++++ b/src/tool_getparam.c +@@ -290,32 +290,33 @@ static const struct feat feats[] = { + {"unix-sockets", CURL_VERSION_UNIX_SOCKETS} + }; + +-/* https://sourceforge.net/p/curl/bugs/1196/ */ ++/* Split the argument of -E to 'certname' and 'passphrase' separated by colon. ++ * We allow ':' and '\' to be escaped by '\' so that we can use certificate ++ * nicknames containing ':'. See ++ * for details. */ + static void parse_cert_parameter(const char *cert_parameter, + char **certname, + char **passphrase) + { + size_t param_length = strlen(cert_parameter); +- size_t parsed_chars = 0; + size_t span; + const char *param_place = NULL; + char *certname_place = NULL; ++ *passphrase = NULL; ++ + /* most trivial assumption: cert_parameter is empty */ + if(param_length == 0) { + *certname = NULL; +- *passphrase = NULL; + return; + } + /* next less trivial: cert_parameter contains no colon nor backslash; this + * means no passphrase was given and no characters escaped */ + if(!strpbrk(cert_parameter, ":\\")) { + *certname = strdup(cert_parameter); +- *passphrase = NULL; + return; + } + /* deal with escaped chars; find unescaped colon if it exists */ + *certname = (char *) malloc(param_length + 1); +- *passphrase = NULL; + param_place = cert_parameter; + certname_place = *certname; + param_place = cert_parameter; +@@ -378,7 +379,6 @@ static void parse_cert_parameter(const char *cert_parameter, + *passphrase = strdup(param_place); + } + return; +- break; + } + } + } +-- +2.7.4 + + +From d9bbc65a4624ba78576e2a7d98dbbeccd4b8a3b3 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 3 May 2013 22:16:46 +0200 +Subject: [PATCH 04/10] tool_getparam: fix memleak in handling the -E option + +Upstream-commit: b47cf4f688297d9cf87a39c8aa328d9d07540e66 +Signed-off-by: Kamil Dudka +--- + src/tool_getparam.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/tool_getparam.c b/src/tool_getparam.c +index 77d44c4..02d95a7 100644 +--- a/src/tool_getparam.c ++++ b/src/tool_getparam.c +@@ -1322,11 +1322,11 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ + { + char *certname, *passphrase; + parse_cert_parameter(nextarg, &certname, &passphrase); +- if(certname) { +- GetStr(&config->cert, certname); +- } ++ Curl_safefree(config->cert); ++ config->cert = certname; + if(passphrase) { +- GetStr(&config->key_passwd, passphrase); ++ Curl_safefree(config->key_passwd); ++ config->key_passwd = passphrase; + } + cleanarg(nextarg); + } +-- +2.7.4 + + +From 0cadf08557da47b826e8f3b3973be2fc80e50068 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 3 May 2013 22:57:18 +0200 +Subject: [PATCH 05/10] tool_getparam: ensure string termination in + parse_cert_parameter() + +Upstream-commit: 2de20dd9a1c6ad4d576c60ab704c30abfc826b1a +Signed-off-by: Kamil Dudka +--- + src/tool_getparam.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +diff --git a/src/tool_getparam.c b/src/tool_getparam.c +index 02d95a7..dd04f5f 100644 +--- a/src/tool_getparam.c ++++ b/src/tool_getparam.c +@@ -302,13 +302,13 @@ static void parse_cert_parameter(const char *cert_parameter, + size_t span; + const char *param_place = NULL; + char *certname_place = NULL; ++ *certname = NULL; + *passphrase = NULL; + + /* most trivial assumption: cert_parameter is empty */ +- if(param_length == 0) { +- *certname = NULL; ++ if(param_length == 0) + return; +- } ++ + /* next less trivial: cert_parameter contains no colon nor backslash; this + * means no passphrase was given and no characters escaped */ + if(!strpbrk(cert_parameter, ":\\")) { +@@ -316,16 +316,17 @@ static void parse_cert_parameter(const char *cert_parameter, + return; + } + /* deal with escaped chars; find unescaped colon if it exists */ +- *certname = (char *) malloc(param_length + 1); +- param_place = cert_parameter; +- certname_place = *certname; ++ certname_place = malloc(param_length + 1); ++ if(!certname_place) ++ return; ++ ++ *certname = certname_place; + param_place = cert_parameter; + while(*param_place) { + span = strcspn(param_place, ":\\"); + strncpy(certname_place, param_place, span); + param_place += span; + certname_place += span; +- *certname_place = '\0'; + /* we just ate all the non-special chars. now we're on either a special + * char or the end of the string. */ + switch(*param_place) { +@@ -378,9 +379,11 @@ static void parse_cert_parameter(const char *cert_parameter, + if(strlen(param_place) > 0) { + *passphrase = strdup(param_place); + } +- return; ++ goto done; + } + } ++done: ++ *certname_place = '\0'; + } + + ParameterError getparameter(char *flag, /* f or -long-flag */ +-- +2.7.4 + + +From 47447c9e89e7f9b5acd60ca565996428d90b9e0e Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 3 May 2013 23:03:58 +0200 +Subject: [PATCH 06/10] src/Makefile.am: build static lib for unit tests if + enabled + +Upstream-commit: 683f2b832388d08999620ee45cb619a7afd42aaf +Signed-off-by: Kamil Dudka +--- + src/Makefile.am | 8 ++++++++ + src/tool_main.c | 4 ++++ + tests/unit/Makefile.am | 11 +++++++++-- + 3 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/src/Makefile.am b/src/Makefile.am +index 6863078..751beda 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -67,6 +67,14 @@ curl_LDFLAGS = @LIBMETALINK_LDFLAGS@ + curl_CPPFLAGS = $(AM_CPPFLAGS) $(LIBMETALINK_CPPFLAGS) + curl_DEPENDENCIES = $(top_builddir)/lib/libcurl.la + ++# if unit tests are enabled, build a static library to link them with ++if BUILD_UNITTESTS ++noinst_LTLIBRARIES = libcurltool.la ++libcurltool_la_CFLAGS = -DUNITTESTS ++libcurltool_la_LDFLAGS = -static $(LINKFLAGS) ++libcurltool_la_SOURCES = $(curl_SOURCES) ++endif ++ + BUILT_SOURCES = tool_hugehelp.c + CLEANFILES = tool_hugehelp.c + # Use the C locale to ensure that only ASCII characters appear in the +diff --git a/src/tool_main.c b/src/tool_main.c +index 6a1ed6c..00d8411 100644 +--- a/src/tool_main.c ++++ b/src/tool_main.c +@@ -59,6 +59,9 @@ + static int vms_show = 0; + #endif + ++/* if we build a static library for unit tests, there is no main() function */ ++#ifndef UNITTESTS ++ + /* + * Ensure that file descriptors 0, 1 and 2 (stdin, stdout, stderr) are + * open before starting to run. Otherwise, the first three network +@@ -128,3 +131,4 @@ int main(int argc, char *argv[]) + #endif + } + ++#endif /* ndef UNITTESTS */ +diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am +index 12d5fe3..ce6af6f 100644 +--- a/tests/unit/Makefile.am ++++ b/tests/unit/Makefile.am +@@ -40,6 +40,7 @@ AM_CPPFLAGS = -I$(top_builddir)/include/curl \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/lib \ ++ -I$(top_srcdir)/src \ + -I$(top_srcdir)/tests/libtest \ + -I$(top_builddir)/ares \ + -I$(top_srcdir)/ares +@@ -49,6 +50,7 @@ AM_CPPFLAGS = -I$(top_builddir)/include/curl \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/lib \ ++ -I$(top_srcdir)/src \ + -I$(top_srcdir)/tests/libtest + endif + +@@ -57,8 +59,13 @@ EXTRA_DIST = Makefile.inc + # Prevent LIBS from being used for all link targets + LIBS = $(BLANK_AT_MAKETIME) + +-LDADD = $(top_builddir)/lib/libcurlu.la @LDFLAGS@ @LIBCURL_LIBS@ +-DEPENDENCIES = $(top_builddir)/lib/libcurlu.la ++LDADD = $(top_builddir)/src/libcurltool.la \ ++ $(top_builddir)/lib/libcurlu.la \ ++ @LDFLAGS@ @LIBCURL_LIBS@ ++ ++DEPENDENCIES = $(top_builddir)/src/libcurltool.la \ ++ $(top_builddir)/lib/libcurlu.la ++ + AM_CPPFLAGS += -DUNITTESTS + + # Mostly for Windows build targets, when using static libcurl +-- +2.7.4 + + +From fb3618a22db456813a3064118e80a55ac2abb8c1 Mon Sep 17 00:00:00 2001 +From: Jared Jennings +Date: Fri, 5 Apr 2013 16:01:31 +0200 +Subject: [PATCH 07/10] unit1394.c: basis of a unit test for + parse_cert_parameter() + +Upstream-commit: b045d079f8bf9e85b2aef94bc94928f444b3a711 +Signed-off-by: Kamil Dudka +--- + tests/unit/unit1394.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 75 insertions(+) + create mode 100644 tests/unit/unit1394.c + +diff --git a/tests/unit/unit1394.c b/tests/unit/unit1394.c +new file mode 100644 +index 0000000..11a47b9 +--- /dev/null ++++ b/tests/unit/unit1394.c +@@ -0,0 +1,75 @@ ++#include ++#include ++#include ++ ++int main(int argc, char **argv) { ++ char *values[] = { ++ /* -E parameter */ /* exp. cert name */ /* exp. passphrase */ ++ "foo:bar:baz", "foo", "bar:baz", ++ "foo\\:bar:baz", "foo:bar", "baz", ++ "foo\\\\:bar:baz", "foo\\", "bar:baz", ++ "foo:bar\\:baz", "foo", "bar\\:baz", ++ "foo:bar\\\\:baz", "foo", "bar\\\\:baz", ++ "foo\\bar\\baz", "foo\\bar\\baz", NULL, ++ "foo\\\\bar\\\\baz", "foo\\bar\\baz", NULL, ++ "foo\\", "foo\\", NULL, ++ "foo\\\\", "foo\\", NULL, ++ "foo:bar\\", "foo", "bar\\", ++ "foo:bar\\\\", "foo", "bar\\\\", ++ "foo:bar:", "foo", "bar:", ++ "foo\\::bar\\:", "foo:", "bar\\:", ++ "c:\\foo:bar:baz", "c:\\foo", "bar:baz", ++ "c:\\foo\\:bar:baz", "c:\\foo:bar", "baz", ++ "c:\\foo\\\\:bar:baz", "c:\\foo\\", "bar:baz", ++ "c:\\foo:bar\\:baz", "c:\\foo", "bar\\:baz", ++ "c:\\foo:bar\\\\:baz", "c:\\foo", "bar\\\\:baz", ++ "c:\\foo\\bar\\baz", "c:\\foo\\bar\\baz", NULL, ++ "c:\\foo\\\\bar\\\\baz", "c:\\foo\\bar\\baz", NULL, ++ "c:\\foo\\", "c:\\foo\\", NULL, ++ "c:\\foo\\\\", "c:\\foo\\", NULL, ++ "c:\\foo:bar\\", "c:\\foo", "bar\\", ++ "c:\\foo:bar\\\\", "c:\\foo", "bar\\\\", ++ "c:\\foo:bar:", "c:\\foo", "bar:", ++ "c:\\foo\\::bar\\:", "c:\\foo:", "bar\\:", ++ NULL, NULL, NULL, ++ }; ++ char **p; ++ char *certname, *passphrase; ++ for(p = values; *p; p += 3) { ++ parse_cert_parameter(p[0], &certname, &passphrase); ++ if(p[1]) { ++ if(certname) { ++ if(strcmp(p[1], certname)) { ++ printf("expected certname '%s' but got '%s' " ++ "for -E param '%s'\n", p[1], certname, p[0]); ++ } ++ } else { ++ printf("expected certname '%s' but got NULL " ++ "for -E param '%s'\n", p[1], p[0]); ++ } ++ } else { ++ if(certname) { ++ printf("expected certname NULL but got '%s' " ++ "for -E param '%s'\n", certname, p[0]); ++ } ++ } ++ if(p[2]) { ++ if(passphrase) { ++ if(strcmp(p[2], passphrase)) { ++ printf("expected passphrase '%s' but got '%s'" ++ "for -E param '%s'\n", p[2], passphrase, p[0]); ++ } ++ } else { ++ printf("expected passphrase '%s' but got NULL " ++ "for -E param '%s'\n", p[2], p[0]); ++ } ++ } else { ++ if(passphrase) { ++ printf("expected passphrase NULL but got '%s' " ++ "for -E param '%s'\n", passphrase, p[0]); ++ } ++ } ++ if(certname) free(certname); ++ if(passphrase) free(passphrase); ++ } ++} +-- +2.7.4 + + +From 2af1560a4b38c33089916cadfe7d8a8e8f44b7d3 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 3 May 2013 13:26:25 +0200 +Subject: [PATCH 08/10] unit1394.c: plug the curl tool unit test in + +Upstream-commit: bcf1b9dec13badd073518e1d63aab40a958d9245 +Signed-off-by: Kamil Dudka +--- + src/tool_getparam.c | 9 +++++--- + src/tool_getparam.h | 6 ++++++ + tests/data/test1394 | 30 ++++++++++++++++++++++++++ + tests/unit/Makefile.inc | 4 +++- + tests/unit/unit1394.c | 56 +++++++++++++++++++++++++++++++++++++++++++++---- + 5 files changed, 97 insertions(+), 8 deletions(-) + create mode 100644 tests/data/test1394 + +diff --git a/src/tool_getparam.c b/src/tool_getparam.c +index dd04f5f..33db742 100644 +--- a/src/tool_getparam.c ++++ b/src/tool_getparam.c +@@ -294,9 +294,12 @@ static const struct feat feats[] = { + * We allow ':' and '\' to be escaped by '\' so that we can use certificate + * nicknames containing ':'. See + * for details. */ +-static void parse_cert_parameter(const char *cert_parameter, +- char **certname, +- char **passphrase) ++#ifndef UNITTESTS ++static ++#endif ++void parse_cert_parameter(const char *cert_parameter, ++ char **certname, ++ char **passphrase) + { + size_t param_length = strlen(cert_parameter); + size_t span; +diff --git a/src/tool_getparam.h b/src/tool_getparam.h +index 38f0674..a86bfce 100644 +--- a/src/tool_getparam.h ++++ b/src/tool_getparam.h +@@ -45,5 +45,11 @@ ParameterError getparameter(char *flag, + bool *usedarg, + struct Configurable *config); + ++#ifdef UNITTESTS ++void parse_cert_parameter(const char *cert_parameter, ++ char **certname, ++ char **passphrase); ++#endif ++ + #endif /* HEADER_CURL_TOOL_GETPARAM_H */ + +diff --git a/tests/data/test1394 b/tests/data/test1394 +new file mode 100644 +index 0000000..34d4a0e +--- /dev/null ++++ b/tests/data/test1394 +@@ -0,0 +1,30 @@ ++ ++ ++ ++unittest ++ ++ ++ ++# ++# Client-side ++ ++ ++none ++ ++ ++unittest ++ ++ ++unit test for parse_cert_parameter() ++ ++ ++unit1394 ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/unit/Makefile.inc b/tests/unit/Makefile.inc +index 20835d7..4490095 100644 +--- a/tests/unit/Makefile.inc ++++ b/tests/unit/Makefile.inc +@@ -6,7 +6,7 @@ UNITFILES = curlcheck.h \ + + # These are all unit test programs + UNITPROGS = unit1300 unit1301 unit1302 unit1303 unit1304 unit1305 unit1307 \ +- unit1308 unit1309 ++ unit1308 unit1309 unit1394 + + unit1300_SOURCES = unit1300.c $(UNITFILES) + unit1300_CPPFLAGS = $(AM_CPPFLAGS) +@@ -35,3 +35,5 @@ unit1308_CPPFLAGS = $(AM_CPPFLAGS) + unit1309_SOURCES = unit1309.c $(UNITFILES) + unit1309_CPPFLAGS = $(AM_CPPFLAGS) + ++unit1394_SOURCES = unit1394.c $(UNITFILES) ++unit1394_CPPFLAGS = $(AM_CPPFLAGS) +diff --git a/tests/unit/unit1394.c b/tests/unit/unit1394.c +index 11a47b9..d25e4f5 100644 +--- a/tests/unit/unit1394.c ++++ b/tests/unit/unit1394.c +@@ -1,9 +1,48 @@ ++/*************************************************************************** ++ * _ _ ____ _ ++ * Project ___| | | | _ \| | ++ * / __| | | | |_) | | ++ * | (__| |_| | _ <| |___ ++ * \___|\___/|_| \_\_____| ++ * ++ * Copyright (C) 1998 - 2013, 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 "curlcheck.h" ++ ++#include "tool_getparam.h" ++ + #include + #include + #include + +-int main(int argc, char **argv) { +- char *values[] = { ++#include "curl_memory.h" ++#include "memdebug.h" /* LAST include file */ ++ ++static CURLcode unit_setup(void) ++{ ++ return CURLE_OK; ++} ++ ++static void unit_stop(void) ++{ ++ ++} ++ ++UNITTEST_START ++ ++ const char *values[] = { + /* -E parameter */ /* exp. cert name */ /* exp. passphrase */ + "foo:bar:baz", "foo", "bar:baz", + "foo\\:bar:baz", "foo:bar", "baz", +@@ -18,6 +57,7 @@ int main(int argc, char **argv) { + "foo:bar\\\\", "foo", "bar\\\\", + "foo:bar:", "foo", "bar:", + "foo\\::bar\\:", "foo:", "bar\\:", ++#ifdef WIN32 + "c:\\foo:bar:baz", "c:\\foo", "bar:baz", + "c:\\foo\\:bar:baz", "c:\\foo:bar", "baz", + "c:\\foo\\\\:bar:baz", "c:\\foo\\", "bar:baz", +@@ -31,9 +71,10 @@ int main(int argc, char **argv) { + "c:\\foo:bar\\\\", "c:\\foo", "bar\\\\", + "c:\\foo:bar:", "c:\\foo", "bar:", + "c:\\foo\\::bar\\:", "c:\\foo:", "bar\\:", ++#endif + NULL, NULL, NULL, + }; +- char **p; ++ const char **p; + char *certname, *passphrase; + for(p = values; *p; p += 3) { + parse_cert_parameter(p[0], &certname, &passphrase); +@@ -42,15 +83,18 @@ int main(int argc, char **argv) { + if(strcmp(p[1], certname)) { + printf("expected certname '%s' but got '%s' " + "for -E param '%s'\n", p[1], certname, p[0]); ++ fail("assertion failure"); + } + } else { + printf("expected certname '%s' but got NULL " + "for -E param '%s'\n", p[1], p[0]); ++ fail("assertion failure"); + } + } else { + if(certname) { + printf("expected certname NULL but got '%s' " + "for -E param '%s'\n", certname, p[0]); ++ fail("assertion failure"); + } + } + if(p[2]) { +@@ -58,18 +102,22 @@ int main(int argc, char **argv) { + if(strcmp(p[2], passphrase)) { + printf("expected passphrase '%s' but got '%s'" + "for -E param '%s'\n", p[2], passphrase, p[0]); ++ fail("assertion failure"); + } + } else { + printf("expected passphrase '%s' but got NULL " + "for -E param '%s'\n", p[2], p[0]); ++ fail("assertion failure"); + } + } else { + if(passphrase) { + printf("expected passphrase NULL but got '%s' " + "for -E param '%s'\n", passphrase, p[0]); ++ fail("assertion failure"); + } + } + if(certname) free(certname); + if(passphrase) free(passphrase); + } +-} ++ ++UNITTEST_STOP +-- +2.7.4 + + +From fc2acbf743634f400efb8ec84748eed7267ead15 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sun, 19 May 2013 12:44:44 +0200 +Subject: [PATCH 09/10] tests: add test1394 file to the tarball + +Upstream-commit: fc4759af9d9cbc7635af0da68c28672a4bbf35ff +Signed-off-by: Kamil Dudka +--- + tests/data/Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 35bc6eb..3b31581 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -90,7 +90,7 @@ test1355 test1356 test1357 test1358 test1359 test1360 test1361 test1362 \ + test1363 test1364 test1365 test1366 test1367 test1368 test1369 test1370 \ + test1371 test1372 test1373 test1374 test1375 test1376 test1377 test1378 \ + test1379 test1380 test1381 test1382 test1383 test1384 test1385 test1386 \ +-test1387 test1388 test1389 test1390 test1391 test1392 test1393 \ ++test1387 test1388 test1389 test1390 test1391 test1392 test1393 test1394 \ + test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \ + test1408 test1409 test1410 test1411 test1412 test1413 test1415 \ + test1435 test1436 \ +-- +2.7.4 + + +From c4fe8629b69e4d5d642d3833a0208b2f65258d31 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 29 Aug 2013 12:50:15 +0200 +Subject: [PATCH 10/10] unit1304: include memdebug and free everything + correctly + +Upstream-commit: d737aa19c89f12c1415637a60afc79a6ea9c649f +Signed-off-by: Kamil Dudka +--- + tests/unit/unit1304.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c +index 9242e80..dcd8fa7 100644 +--- a/tests/unit/unit1304.c ++++ b/tests/unit/unit1304.c +@@ -5,7 +5,7 @@ + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * +- * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. ++ * Copyright (C) 1998 - 2013, 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 +@@ -20,8 +20,8 @@ + * + ***************************************************************************/ + #include "curlcheck.h" +- + #include "netrc.h" ++#include "memdebug.h" /* LAST include file */ + + static char *login; + static char *password; +@@ -144,6 +144,9 @@ UNITTEST_START + "password should be 'none'"); + fail_unless(strncmp(login, "none", 4) == 0, "login should be 'none'"); + ++ free(login); ++ free(password); ++ + /* TODO: + * Test over the size limit password / login! + * Test files with a bad format +-- +2.7.4 + diff --git a/SOURCES/0046-curl-7.29.0-049aa925.patch b/SOURCES/0046-curl-7.29.0-049aa925.patch new file mode 100644 index 0000000..babd456 --- /dev/null +++ b/SOURCES/0046-curl-7.29.0-049aa925.patch @@ -0,0 +1,103 @@ +From 301f5142f8eac474ff3f92d83450cdd3b023c92b Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 19 Sep 2016 16:37:05 +0200 +Subject: [PATCH 1/3] nss: fix typo in ecdhe_rsa_null cipher suite string + +As it seems to be a rarely used cipher suite (for securely established +but _unencrypted_ connections), I believe it is fine not to provide an +alias for the misspelled variant. + +Upstream-commit: 75912202709e0f74a5bab91ef57254d7038f5f42 +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 7b4fe57..d0db3cd 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -144,7 +144,7 @@ static const cipher_s cipherlist[] = { + {"ecdh_rsa_3des_sha", TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdh_rsa_aes_128_sha", TLS_ECDH_RSA_WITH_AES_128_CBC_SHA}, + {"ecdh_rsa_aes_256_sha", TLS_ECDH_RSA_WITH_AES_256_CBC_SHA}, +- {"echde_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA}, ++ {"ecdhe_rsa_null", TLS_ECDHE_RSA_WITH_NULL_SHA}, + {"ecdhe_rsa_rc4_128_sha", TLS_ECDHE_RSA_WITH_RC4_128_SHA}, + {"ecdhe_rsa_3des_sha", TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA}, + {"ecdhe_rsa_aes_128_sha", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA}, +-- +2.7.4 + + +From 3b11781032d9c04ba8a9500899339a4758da4ad7 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 19 Sep 2016 17:38:23 +0200 +Subject: [PATCH 2/3] nss: add cipher suites using SHA384 if supported by NSS + +Upstream-commit: 049aa9254687f6738642bd73da9bf96d8af2a833 +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 d0db3cd..16b0218 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -174,6 +174,16 @@ static const cipher_s cipherlist[] = { + {"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 ++#ifdef TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ++ /* cipher suites using SHA384 */ ++ {"rsa_aes_256_gcm_sha_384", TLS_RSA_WITH_AES_256_GCM_SHA384}, ++ {"dhe_rsa_aes_256_gcm_sha_384", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384}, ++ {"dhe_dss_aes_256_gcm_sha_384", TLS_DHE_DSS_WITH_AES_256_GCM_SHA384}, ++ {"ecdhe_ecdsa_aes_256_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384}, ++ {"ecdhe_rsa_aes_256_sha_384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384}, ++ {"ecdhe_ecdsa_aes_256_gcm_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}, ++ {"ecdhe_rsa_aes_256_gcm_sha_384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, ++#endif + }; + + static const char* pem_library = "libnsspem.so"; +-- +2.7.4 + + +From e796e68d2f1ef647a91afa10deb0986e082a14be Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 19 Sep 2016 17:45:53 +0200 +Subject: [PATCH 3/3] nss: add chacha20-poly1305 cipher suites if supported by + NSS + +Upstream-commit: d1f1c857ad559eafef9373621d30174c046261ef +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/lib/nss.c b/lib/nss.c +index 16b0218..36c100d 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -184,6 +184,15 @@ static const cipher_s cipherlist[] = { + {"ecdhe_ecdsa_aes_256_gcm_sha_384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384}, + {"ecdhe_rsa_aes_256_gcm_sha_384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384}, + #endif ++#ifdef TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 ++ /* chacha20-poly1305 cipher suites */ ++ {"ecdhe_rsa_chacha20_poly1305_sha_256", ++ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, ++ {"ecdhe_ecdsa_chacha20_poly1305_sha_256", ++ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256}, ++ {"dhe_rsa_chacha20_poly1305_sha_256", ++ TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256}, ++#endif + }; + + static const char* pem_library = "libnsspem.so"; +-- +2.7.4 + diff --git a/SOURCES/0047-curl-7.29.0-85b9dc80.patch b/SOURCES/0047-curl-7.29.0-85b9dc80.patch new file mode 100644 index 0000000..aec8768 --- /dev/null +++ b/SOURCES/0047-curl-7.29.0-85b9dc80.patch @@ -0,0 +1,151 @@ +From 5f543b36b2b05cbe52a9861ad7cb15e0a7c78c80 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 21 May 2013 23:28:59 +0200 +Subject: [PATCH] Curl_cookie_add: handle IPv6 hosts + +1 - don't skip host names with a colon in them in an attempt to bail out +on HTTP headers in the cookie file parser. It was only a shortcut anyway +and trying to parse a file with HTTP headers will still be handled, only +slightly slower. + +2 - don't skip domain names based on number of dots. The original +netscape cookie spec had this oddity mentioned and while our code +decreased the check to only check for two, the existing cookie spec has +no such dot counting required. + +Bug: http://curl.haxx.se/bug/view.cgi?id=1221 +Reported-by: Stefan Neis + +Upstream-commit: 85b9dc80232d1d7d48ee4dea6db5a2263ee68efd +Signed-off-by: Kamil Dudka +--- + lib/cookie.c | 93 +++++++++++++++++------------------------------------------- + 1 file changed, 26 insertions(+), 67 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index 764bbc9..956efd4 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -347,6 +347,9 @@ static bool isip(const char *domain) + * + * Add a single cookie line to the cookie keeping object. + * ++ * Be aware that sometimes we get an IP-only host name, and that might also be ++ * a numerical IPv6 address. ++ * + ***************************************************************************/ + + struct Cookie * +@@ -458,73 +461,35 @@ Curl_cookie_add(struct SessionHandle *data, + } + } + else if(Curl_raw_equal("domain", name)) { +- /* note that this name may or may not have a preceding dot, but +- we don't care about that, we treat the names the same anyway */ +- +- const char *domptr=whatptr; +- const char *nextptr; +- int dotcount=1; ++ bool is_ip; + +- /* Count the dots, we need to make sure that there are enough +- of them. */ ++ /* 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]) +- /* don't count the initial dot, assume it */ +- domptr++; +- +- do { +- nextptr = strchr(domptr, '.'); +- if(nextptr) { +- if(domptr != nextptr) +- dotcount++; +- domptr = nextptr+1; ++ whatptr++; /* ignore preceding dot */ ++ ++ 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; + } +- } while(nextptr); +- +- /* The original Netscape cookie spec defined that this domain name +- MUST have three dots (or two if one of the seven holy TLDs), +- but it seems that these kinds of cookies are in use "out there" +- so we cannot be that strict. I've therefore lowered the check +- to not allow less than two dots. */ +- +- if(dotcount < 2) { +- /* Received and skipped a cookie with a domain using too few +- dots. */ +- badcookie=TRUE; /* mark this as a bad cookie */ +- infof(data, "skipped cookie with illegal dotcount domain: %s\n", +- whatptr); ++ if(!is_ip) ++ co->tailmatch=TRUE; /* we always do that if the domain name was ++ given */ + } + 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 */ +- +- 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; +- } +- 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 +- is not a domain to which the current host belongs. Mark as +- bad. */ +- badcookie=TRUE; +- infof(data, "skipped cookie with bad tailmatch domain: %s\n", +- whatptr); +- } ++ /* we did not get a tailmatch and then the attempted set domain ++ is not a domain to which the current host belongs. Mark as ++ bad. */ ++ badcookie=TRUE; ++ infof(data, "skipped cookie with bad tailmatch domain: %s\n", ++ whatptr); + } + } + else if(Curl_raw_equal("version", name)) { +@@ -696,12 +661,6 @@ Curl_cookie_add(struct SessionHandle *data, + + firstptr=strtok_r(lineptr, "\t", &tok_buf); /* tokenize it on the TAB */ + +- /* Here's a quick check to eliminate normal HTTP-headers from this */ +- if(!firstptr || strchr(firstptr, ':')) { +- free(co); +- return NULL; +- } +- + /* Now loop through the fields and init the struct we already have + allocated */ + for(ptr=firstptr, fields=0; ptr && !badcookie; +-- +2.5.5 + diff --git a/SOURCES/0048-curl-7.29.0-eb84412b.patch b/SOURCES/0048-curl-7.29.0-eb84412b.patch new file mode 100644 index 0000000..64b950e --- /dev/null +++ b/SOURCES/0048-curl-7.29.0-eb84412b.patch @@ -0,0 +1,36 @@ +From 9a84abe8bd4951f8674e172acf1335d3be961d73 Mon Sep 17 00:00:00 2001 +From: Martin Frodl +Date: Mon, 24 Oct 2016 17:44:45 +0200 +Subject: [PATCH] nss: fix tight loop in non-blocking TLS handhsake over proxy + +... in case the handshake completes before entering +CURLM_STATE_PROTOCONNECT + +Bug: https://bugzilla.redhat.com/1388162 + +Upstream-commit: eb84412b33aa9cbe109d3e2874f9dbba48043263 +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 36c100d..848ce86 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1603,8 +1603,11 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, + const bool blocking = (done == NULL); + CURLcode rv; + +- if(connssl->state == ssl_connection_complete) ++ if(connssl->state == ssl_connection_complete) { ++ if(!blocking) ++ *done = TRUE; + return CURLE_OK; ++ } + + if(connssl->connecting_state == ssl_connect_1) { + rv = nss_setup_connect(conn, sockindex); +-- +2.7.4 + diff --git a/SOURCES/0049-curl-7.29.0-8fa54098.patch b/SOURCES/0049-curl-7.29.0-8fa54098.patch new file mode 100644 index 0000000..66330ad --- /dev/null +++ b/SOURCES/0049-curl-7.29.0-8fa54098.patch @@ -0,0 +1,849 @@ +From bf2eb071494dd48bf1730ce2bc7d21a8fd13b5c8 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 26 Oct 2013 20:19:27 +0200 +Subject: [PATCH 1/7] FTP: make the data connection work when going through + proxy + +This is a regression since the switch to always-multi internally +c43127414d89c. + +Upstream-commit: d44b0142714041b784ffd10792318674ecb1ed56 +Signed-off-by: Kamil Dudka +--- + lib/connect.c | 2 +- + lib/ftp.c | 183 +++++++++++++++++++++++++++++++--------------------------- + lib/ftp.h | 6 ++ + lib/socks.c | 4 ++ + lib/url.c | 9 ++- + lib/url.h | 2 +- + 6 files changed, 117 insertions(+), 89 deletions(-) + +diff --git a/lib/connect.c b/lib/connect.c +index 5aa53fe..78627e6 100644 +--- a/lib/connect.c ++++ b/lib/connect.c +@@ -715,7 +715,7 @@ CURLcode Curl_is_connected(struct connectdata *conn, + /* we are connected with TCP, awesome! */ + + /* see if we need to do any proxy magic first once we connected */ +- code = Curl_connected_proxy(conn); ++ code = Curl_connected_proxy(conn, sockindex); + if(code) + return code; + +diff --git a/lib/ftp.c b/lib/ftp.c +index 63d1e64..b9fa12e 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -1800,6 +1800,79 @@ static CURLcode ftp_epsv_disable(struct connectdata *conn) + return result; + } + ++/* ++ * Perform the necessary magic that needs to be done once the TCP connection ++ * to the proxy has completed. ++ */ ++static CURLcode proxy_magic(struct connectdata *conn, ++ char *newhost, unsigned short newport, ++ bool *magicdone) ++{ ++ struct SessionHandle *data=conn->data; ++ CURLcode result; ++ ++ *magicdone = FALSE; ++ switch(conn->proxytype) { ++ case CURLPROXY_SOCKS5: ++ case CURLPROXY_SOCKS5_HOSTNAME: ++ result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, ++ newport, SECONDARYSOCKET, conn); ++ *magicdone = TRUE; ++ break; ++ case CURLPROXY_SOCKS4: ++ result = Curl_SOCKS4(conn->proxyuser, newhost, newport, ++ SECONDARYSOCKET, conn, FALSE); ++ *magicdone = TRUE; ++ break; ++ case CURLPROXY_SOCKS4A: ++ result = Curl_SOCKS4(conn->proxyuser, newhost, newport, ++ SECONDARYSOCKET, conn, TRUE); ++ *magicdone = TRUE; ++ break; ++ case CURLPROXY_HTTP: ++ case CURLPROXY_HTTP_1_0: ++ /* do nothing here. handled later. */ ++ break; ++ default: ++ failf(data, "unknown proxytype option given"); ++ result = CURLE_COULDNT_CONNECT; ++ break; ++ } ++ ++ if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { ++ /* BLOCKING */ ++ /* We want "seamless" FTP operations through HTTP proxy tunnel */ ++ ++ /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the ++ * member conn->proto.http; we want FTP through HTTP and we have to ++ * change the member temporarily for connecting to the HTTP proxy. After ++ * Curl_proxyCONNECT we have to set back the member to the original ++ * struct FTP pointer ++ */ ++ struct HTTP http_proxy; ++ struct FTP *ftp_save = data->state.proto.ftp; ++ memset(&http_proxy, 0, sizeof(http_proxy)); ++ data->state.proto.http = &http_proxy; ++ ++ result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport); ++ ++ data->state.proto.ftp = ftp_save; ++ ++ if(result) ++ return result; ++ ++ if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) { ++ /* the CONNECT procedure is not complete, the tunnel is not yet up */ ++ state(conn, FTP_STOP); /* this phase is completed */ ++ conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; ++ return result; ++ } ++ else ++ *magicdone = TRUE; ++ } ++ return result; ++} ++ + static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + int ftpcode) + { +@@ -1810,13 +1883,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + struct Curl_dns_entry *addr=NULL; + int rc; + unsigned short connectport; /* the local port connect() should use! */ +- unsigned short newport=0; /* remote port */ + bool connected; +- +- /* newhost must be able to hold a full IP-style address in ASCII, which +- in the IPv6 case means 5*8-1 = 39 letters */ +-#define NEWHOST_BUFSIZE 48 +- char newhost[NEWHOST_BUFSIZE]; + char *str=&data->state.buffer[4]; /* start on the first letter */ + + if((ftpc->count1 == 0) && +@@ -1849,7 +1916,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + return CURLE_FTP_WEIRD_PASV_REPLY; + } + if(ptr) { +- newport = (unsigned short)(num & 0xffff); ++ ftpc->newport = (unsigned short)(num & 0xffff); + + if(conn->bits.tunnel_proxy || + conn->proxytype == CURLPROXY_SOCKS5 || +@@ -1858,10 +1925,11 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + conn->proxytype == CURLPROXY_SOCKS4A) + /* proxy tunnel -> use other host info because ip_addr_str is the + proxy address not the ftp host */ +- snprintf(newhost, sizeof(newhost), "%s", conn->host.name); ++ snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s", ++ conn->host.name); + else + /* use the same IP we are already connected to */ +- snprintf(newhost, NEWHOST_BUFSIZE, "%s", conn->ip_addr_str); ++ snprintf(ftpc->newhost, NEWHOST_BUFSIZE, "%s", conn->ip_addr_str); + } + } + else +@@ -1914,14 +1982,15 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + conn->proxytype == CURLPROXY_SOCKS4A) + /* proxy tunnel -> use other host info because ip_addr_str is the + proxy address not the ftp host */ +- snprintf(newhost, sizeof(newhost), "%s", conn->host.name); ++ snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s", conn->host.name); + else +- snprintf(newhost, sizeof(newhost), "%s", conn->ip_addr_str); ++ snprintf(ftpc->newhost, sizeof(ftpc->newhost), "%s", ++ conn->ip_addr_str); + } + else +- snprintf(newhost, sizeof(newhost), ++ snprintf(ftpc->newhost, sizeof(ftpc->newhost), + "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); +- newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); ++ ftpc->newport = (unsigned short)(((port[0]<<8) + port[1]) & 0xffff); + } + else if(ftpc->count1 == 0) { + /* EPSV failed, move on to PASV */ +@@ -1957,15 +2026,15 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + } + else { + /* normal, direct, ftp connection */ +- rc = Curl_resolv(conn, newhost, newport, &addr); ++ rc = Curl_resolv(conn, ftpc->newhost, ftpc->newport, &addr); + if(rc == CURLRESOLV_PENDING) + /* BLOCKING */ + (void)Curl_resolver_wait_resolv(conn, &addr); + +- connectport = newport; /* we connect to the remote port */ ++ connectport = ftpc->newport; /* we connect to the remote port */ + + if(!addr) { +- failf(data, "Can't resolve new host %s:%hu", newhost, connectport); ++ failf(data, "Can't resolve new host %s:%hu", ftpc->newhost, connectport); + return CURLE_FTP_CANT_GET_HOST; + } + } +@@ -1990,80 +2059,20 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + /* + * When this is used from the multi interface, this might've returned with + * the 'connected' set to FALSE and thus we are now awaiting a non-blocking +- * connect to connect and we should not be "hanging" here waiting. ++ * connect to connect. + */ + + if(data->set.verbose) + /* this just dumps information about this second connection */ +- ftp_pasv_verbose(conn, conninfo, newhost, connectport); +- +- switch(conn->proxytype) { +- /* FIX: this MUST wait for a proper connect first if 'connected' is +- * FALSE */ +- case CURLPROXY_SOCKS5: +- case CURLPROXY_SOCKS5_HOSTNAME: +- result = Curl_SOCKS5(conn->proxyuser, conn->proxypasswd, newhost, newport, +- SECONDARYSOCKET, conn); +- connected = TRUE; +- break; +- case CURLPROXY_SOCKS4: +- result = Curl_SOCKS4(conn->proxyuser, newhost, newport, +- SECONDARYSOCKET, conn, FALSE); +- connected = TRUE; +- break; +- case CURLPROXY_SOCKS4A: +- result = Curl_SOCKS4(conn->proxyuser, newhost, newport, +- SECONDARYSOCKET, conn, TRUE); +- connected = TRUE; +- break; +- case CURLPROXY_HTTP: +- case CURLPROXY_HTTP_1_0: +- /* do nothing here. handled later. */ +- break; +- default: +- failf(data, "unknown proxytype option given"); +- result = CURLE_COULDNT_CONNECT; +- break; +- } +- +- if(result) { +- if(ftpc->count1 == 0 && ftpcode == 229) +- return ftp_epsv_disable(conn); +- return result; +- } +- +- if(conn->bits.tunnel_proxy && conn->bits.httpproxy) { +- /* FIX: this MUST wait for a proper connect first if 'connected' is +- * FALSE */ +- +- /* BLOCKING */ +- /* We want "seamless" FTP operations through HTTP proxy tunnel */ +- +- /* Curl_proxyCONNECT is based on a pointer to a struct HTTP at the member +- * conn->proto.http; we want FTP through HTTP and we have to change the +- * member temporarily for connecting to the HTTP proxy. After +- * Curl_proxyCONNECT we have to set back the member to the original struct +- * FTP pointer +- */ +- struct HTTP http_proxy; +- struct FTP *ftp_save = data->state.proto.ftp; +- memset(&http_proxy, 0, sizeof(http_proxy)); +- data->state.proto.http = &http_proxy; +- +- result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport); ++ ftp_pasv_verbose(conn, conninfo, ftpc->newhost, connectport); + +- data->state.proto.ftp = ftp_save; +- +- if(result) +- return result; +- +- if(conn->tunnel_state[SECONDARYSOCKET] != TUNNEL_COMPLETE) { +- /* the CONNECT procedure is not complete, the tunnel is not yet up */ +- state(conn, FTP_STOP); /* this phase is completed */ +- conn->bits.tcpconnect[SECONDARYSOCKET] = FALSE; +- +- return result; +- } ++ if(connected) { ++ /* Only do the proxy connection magic if we're actually connected. We do ++ this little trick and send in the same 'connected' variable here again ++ and it will be set FALSE by proxy_magic() for when for example the ++ CONNECT procedure doesn't complete */ ++ infof(data, "Connection to proxy confirmed almost instantly\n"); ++ result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected); + } + + conn->bits.tcpconnect[SECONDARYSOCKET] = connected; +@@ -3686,6 +3695,10 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) + /* Ready to do more? */ + if(connected) { + DEBUGF(infof(data, "DO-MORE connected phase starts\n")); ++ if(conn->bits.proxy) { ++ infof(data, "Connection to proxy confirmed\n"); ++ result = proxy_magic(conn, ftpc->newhost, ftpc->newport, &connected); ++ } + } + else { + if(result && (ftpc->count1 == 0)) { +diff --git a/lib/ftp.h b/lib/ftp.h +index d359f28..4b4a488 100644 +--- a/lib/ftp.h ++++ b/lib/ftp.h +@@ -154,6 +154,12 @@ struct ftp_conn { + curl_off_t known_filesize; /* file size is different from -1, if wildcard + LIST parsing was done and wc_statemach set + it */ ++ /* newhost must be able to hold a full IP-style address in ASCII, which ++ in the IPv6 case means 5*8-1 = 39 letters */ ++#define NEWHOST_BUFSIZE 48 ++ char newhost[NEWHOST_BUFSIZE]; /* this is the pair to connect the DATA... */ ++ unsigned short newport; /* connection to */ ++ + }; + + #define DEFAULT_ACCEPT_TIMEOUT 60000 /* milliseconds == one minute */ +diff --git a/lib/socks.c b/lib/socks.c +index 51bb946..0cf397c 100644 +--- a/lib/socks.c ++++ b/lib/socks.c +@@ -129,6 +129,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name, + + curlx_nonblock(sock, FALSE); + ++ infof(data, "SOCKS4 communication to %s:%d\n", hostname, remote_port); ++ + /* + * Compose socks4 request + * +@@ -182,6 +184,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name, + else + hp = NULL; /* fail! */ + ++ infof(data, "SOCKS4 connect to %s (locally resolved)\n", buf); ++ + Curl_resolv_unlock(data, dns); /* not used anymore from now on */ + + } +diff --git a/lib/url.c b/lib/url.c +index cfc2744..11e0ff5 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -3103,8 +3103,13 @@ static CURLcode ConnectionStore(struct SessionHandle *data, + Note: this function's sub-functions call failf() + + */ +-CURLcode Curl_connected_proxy(struct connectdata *conn) ++CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex) + { ++ if(!conn->bits.proxy || sockindex) ++ /* this magic only works for the primary socket as the secondary is used ++ for FTP only and it has FTP specific magic in ftp.c */ ++ return CURLE_OK; ++ + switch(conn->proxytype) { + #ifndef CURL_DISABLE_PROXY + case CURLPROXY_SOCKS5: +@@ -3162,7 +3167,7 @@ static CURLcode ConnectPlease(struct SessionHandle *data, + conn->ip_addr = addr; + + if(*connected) { +- result = Curl_connected_proxy(conn); ++ result = Curl_connected_proxy(conn, FIRSTSOCKET); + if(!result) { + conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; + Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ +diff --git a/lib/url.h b/lib/url.h +index c0d9c38..1da9be3 100644 +--- a/lib/url.h ++++ b/lib/url.h +@@ -74,7 +74,7 @@ void Curl_reset_reqproto(struct connectdata *conn); + #define CURL_DEFAULT_SOCKS5_GSSAPI_SERVICE "rcmd" /* default socks5 gssapi + service */ + +-CURLcode Curl_connected_proxy(struct connectdata *conn); ++CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex); + + #ifdef CURL_DISABLE_VERBOSE_STRINGS + #define Curl_verboseconnect(x) Curl_nop_stmt +-- +2.9.3 + + +From 4157798db51c859a1130203cebf377e77f56398a Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sun, 27 Oct 2013 00:00:01 +0100 +Subject: [PATCH 2/7] ftp: Fixed compiler warning + +warning: 'result' may be used uninitialized in this function + +Upstream-commit: 9f503a254b0c720706124cb75922a0123f0079f0 +Signed-off-by: Kamil Dudka +--- + lib/ftp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/lib/ftp.c b/lib/ftp.c +index b9fa12e..9c863b9 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -1808,8 +1808,8 @@ static CURLcode proxy_magic(struct connectdata *conn, + char *newhost, unsigned short newport, + bool *magicdone) + { ++ CURLcode result = CURLE_OK; + struct SessionHandle *data=conn->data; +- CURLcode result; + + *magicdone = FALSE; + switch(conn->proxytype) { +-- +2.9.3 + + +From 30566b76d17d9c5e13e3af621ecae0f4cafc3ac8 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 19 Jul 2014 23:58:58 +0200 +Subject: [PATCH 3/7] CONNECT: Revert Curl_proxyCONNECT back to 7.29.0 design + +This reverts commit cb3e6dfa3511 and instead fixes the problem +differently. + +The reverted commit addressed a test failure in test 1021 by simplifying +and generalizing the code flow in a way that damaged the +performance. Now we modify the flow so that Curl_proxyCONNECT() again +does as much as possible in one go, yet still do test 1021 with and +without valgrind. It failed due to mistakes in the multi state machine. + +Bug: http://curl.haxx.se/bug/view.cgi?id=1397 +Reported-by: Paul Saab + +Upstream-commit: a4cece3d47cf092da00cf9910e87bb60b9eff533 +Signed-off-by: Kamil Dudka +--- + lib/http_proxy.c | 47 ++++++++++++++++++++++++++++++----------------- + lib/multi.c | 16 ++++++++++------ + 2 files changed, 40 insertions(+), 23 deletions(-) + +diff --git a/lib/http_proxy.c b/lib/http_proxy.c +index c2eb667..d311b89 100644 +--- a/lib/http_proxy.c ++++ b/lib/http_proxy.c +@@ -98,8 +98,6 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, + struct SessionHandle *data=conn->data; + struct SingleRequest *k = &data->req; + CURLcode result; +- long timeout = +- data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */ + curl_socket_t tunnelsocket = conn->sock[sockindex]; + curl_off_t cl=0; + bool closeConnection = FALSE; +@@ -223,14 +221,25 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, + return result; + + conn->tunnel_state[sockindex] = TUNNEL_CONNECT; ++ } /* END CONNECT PHASE */ ++ ++ check = Curl_timeleft(data, NULL, TRUE); ++ if(check <= 0) { ++ failf(data, "Proxy CONNECT aborted due to timeout"); ++ return CURLE_RECV_ERROR; ++ } + +- /* now we've issued the CONNECT and we're waiting to hear back, return +- and get called again polling-style */ ++ if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0)) ++ /* return so we'll be called again polling-style */ + return CURLE_OK; ++ else { ++ DEBUGF(infof(data, ++ "Read response immediately from proxy CONNECT\n")); ++ } + +- } /* END CONNECT PHASE */ ++ /* at this point, the tunnel_connecting phase is over. */ + +- { /* BEGIN NEGOTIATION PHASE */ ++ { /* READING RESPONSE PHASE */ + size_t nread; /* total size read */ + int perline; /* count bytes per line */ + int keepon=TRUE; +@@ -247,9 +256,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, + + while((nreadnow); /* spent time */ ++ check = Curl_timeleft(data, NULL, TRUE); + if(check <= 0) { + failf(data, "Proxy CONNECT aborted due to timeout"); + error = SELECT_TIMEOUT; /* already too little time */ +@@ -279,6 +286,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, + /* proxy auth was requested and there was proxy auth available, + then deem this as "mere" proxy disconnect */ + conn->bits.proxy_connect_closed = TRUE; ++ infof(data, "Proxy CONNECT connection closed"); + } + else { + error = SELECT_ERROR; +@@ -519,7 +527,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, + conn->sock[sockindex] = CURL_SOCKET_BAD; + break; + } +- } /* END NEGOTIATION PHASE */ ++ } /* END READING RESPONSE PHASE */ + + /* If we are supposed to continue and request a new URL, which basically + * means the HTTP authentication is still going on so if the tunnel +@@ -534,13 +542,11 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, + } while(data->req.newurl); + + if(200 != data->req.httpcode) { +- failf(data, "Received HTTP code %d from proxy after CONNECT", +- data->req.httpcode); +- +- if(closeConnection && data->req.newurl) ++ if(closeConnection && data->req.newurl) { + conn->bits.proxy_connect_closed = TRUE; +- +- if(data->req.newurl) { ++ infof(data, "Connect me again please\n"); ++ } ++ else if(data->req.newurl) { + /* this won't be used anymore for the CONNECT so free it now */ + free(data->req.newurl); + data->req.newurl = NULL; +@@ -549,7 +555,14 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, + /* to back to init state */ + conn->tunnel_state[sockindex] = TUNNEL_INIT; + +- return CURLE_RECV_ERROR; ++ if(conn->bits.proxy_connect_closed) ++ /* this is not an error, just part of the connection negotiation */ ++ return CURLE_OK; ++ else { ++ failf(data, "Received HTTP code %d from proxy after CONNECT", ++ data->req.httpcode); ++ return CURLE_RECV_ERROR; ++ } + } + + conn->tunnel_state[sockindex] = TUNNEL_COMPLETE; +diff --git a/lib/multi.c b/lib/multi.c +index 0e0bb19..3029fa6 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -1134,11 +1134,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, + easy->result = Curl_http_connect(easy->easy_conn, &protocol_connect); + + if(easy->easy_conn->bits.proxy_connect_closed) { +- /* reset the error buffer */ +- if(data->set.errorbuffer) +- data->set.errorbuffer[0] = '\0'; +- data->state.errorbuf = FALSE; +- ++ /* connect back to proxy again */ + easy->result = CURLE_OK; + result = CURLM_CALL_MULTI_PERFORM; + multistate(easy, CURLM_STATE_CONNECT); +@@ -1164,7 +1160,15 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, + &protocol_connect); + } + +- if(CURLE_OK != easy->result) { ++ if(easy->easy_conn->bits.proxy_connect_closed) { ++ /* connect back to proxy again since it was closed in a proxy CONNECT ++ setup */ ++ easy->result = CURLE_OK; ++ result = CURLM_CALL_MULTI_PERFORM; ++ multistate(easy, CURLM_STATE_CONNECT); ++ break; ++ } ++ else if(CURLE_OK != easy->result) { + /* failure detected */ + /* Just break, the cleaning up is handled all in one place */ + disconnect_conn = TRUE; +-- +2.9.3 + + +From 6ab9346d63e88ddfb8fd3f509ad350cab24c37f4 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Wed, 17 Jun 2015 00:30:06 +0200 +Subject: [PATCH 4/7] FTP: do the HTTP CONNECT for data connection blocking + +** WORK-AROUND ** + +The introduced non-blocking general behaviour for Curl_proxyCONNECT() +didn't work for the data connection establishment unless it was very +fast. The newly introduced function argument makes it operate in a more +blocking manner, more like it used to work in the past. This blocking +approach is only used when the FTP data connecting through HTTP proxy. + +Blocking like this is bad. A better fix would make it work more +asynchronously. + +Bug: https://github.com/bagder/curl/issues/278 + +Upstream-commit: b88f980a7437abc1159a1185c04d381347c8f5b1 +Signed-off-by: Kamil Dudka +--- + lib/ftp.c | 4 ++-- + lib/http_proxy.c | 22 ++++++++++++++-------- + lib/http_proxy.h | 3 ++- + 3 files changed, 18 insertions(+), 11 deletions(-) + +diff --git a/lib/ftp.c b/lib/ftp.c +index 63d1e64..db1e29e 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -1854,7 +1854,7 @@ static CURLcode proxy_magic(struct connectdata *conn, + memset(&http_proxy, 0, sizeof(http_proxy)); + data->state.proto.http = &http_proxy; + +- result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport); ++ result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, newhost, newport, TRUE); + + data->state.proto.ftp = ftp_save; + +@@ -3685,7 +3685,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep) + if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) { + /* As we're in TUNNEL_CONNECT state now, we know the proxy name and port + aren't used so we blank their arguments. TODO: make this nicer */ +- result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0); ++ result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE); + + return result; + } +diff --git a/lib/http_proxy.c b/lib/http_proxy.c +index d311b89..4ab280f 100644 +--- a/lib/http_proxy.c ++++ b/lib/http_proxy.c +@@ -71,7 +71,7 @@ CURLcode Curl_proxy_connect(struct connectdata *conn) + conn->data->state.proto.http = &http_proxy; + conn->bits.close = FALSE; + result = Curl_proxyCONNECT(conn, FIRSTSOCKET, +- conn->host.name, conn->remote_port); ++ conn->host.name, conn->remote_port, FALSE); + conn->data->state.proto.generic = prot_save; + if(CURLE_OK != result) + return result; +@@ -87,12 +87,16 @@ CURLcode Curl_proxy_connect(struct connectdata *conn) + * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This + * function will issue the necessary commands to get a seamless tunnel through + * this proxy. After that, the socket can be used just as a normal socket. ++ * ++ * 'blocking' set to TRUE means that this function will do the entire CONNECT ++ * + response in a blocking fashion. Should be avoided! + */ + + CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int sockindex, + const char *hostname, +- unsigned short remote_port) ++ unsigned short remote_port, ++ bool blocking) + { + int subversion=0; + struct SessionHandle *data=conn->data; +@@ -229,12 +233,14 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn, + return CURLE_RECV_ERROR; + } + +- if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0)) +- /* return so we'll be called again polling-style */ +- return CURLE_OK; +- else { +- DEBUGF(infof(data, +- "Read response immediately from proxy CONNECT\n")); ++ if(!blocking) { ++ if(0 == Curl_socket_ready(tunnelsocket, CURL_SOCKET_BAD, 0)) ++ /* return so we'll be called again polling-style */ ++ return CURLE_OK; ++ else { ++ DEBUGF(infof(data, ++ "Read response immediately from proxy CONNECT\n")); ++ } + } + + /* at this point, the tunnel_connecting phase is over. */ +diff --git a/lib/http_proxy.h b/lib/http_proxy.h +index 518c093..4dddc3b 100644 +--- a/lib/http_proxy.h ++++ b/lib/http_proxy.h +@@ -26,7 +26,8 @@ + /* ftp can use this as well */ + CURLcode Curl_proxyCONNECT(struct connectdata *conn, + int tunnelsocket, +- const char *hostname, unsigned short remote_port); ++ const char *hostname, unsigned short remote_port, ++ bool blocking); + + /* Default proxy timeout in milliseconds */ + #define PROXY_TIMEOUT (3600*1000) +-- +2.9.3 + + +From 7be64d4d3e1b966d491c6cde4fe3b6d69f03185b Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Thu, 9 Feb 2017 16:21:52 +0100 +Subject: [PATCH 5/7] nss: make FTPS work with --proxytunnel + +If the NSS code was in the middle of a non-blocking handshake and it +was asked to finish the handshake in blocking mode, it unexpectedly +continued in the non-blocking mode, which caused a FTPS connection +over CONNECT to fail with "(81) Socket not ready for send/recv". + +Bug: https://bugzilla.redhat.com/1420327 + +Upstream-commit: 8fa5409800668ad5305e7517597286014c7708fb +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 23 +++++++++++------------ + 1 file changed, 11 insertions(+), 12 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 848ce86..cf45f3a 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1305,13 +1305,14 @@ static CURLcode nss_fail_connect(struct ssl_connect_data *connssl, + return curlerr; + } + +-/* Switch the SSL socket into non-blocking mode. */ +-static CURLcode nss_set_nonblock(struct ssl_connect_data *connssl, +- struct SessionHandle *data) ++/* Switch the SSL socket into blocking or non-blocking mode. */ ++static CURLcode nss_set_blocking(struct ssl_connect_data *connssl, ++ struct SessionHandle *data, ++ bool blocking) + { + static PRSocketOptionData sock_opt; + sock_opt.option = PR_SockOpt_Nonblocking; +- sock_opt.value.non_blocking = PR_TRUE; ++ sock_opt.value.non_blocking = !blocking; + + if(PR_SetSocketOption(connssl->handle, &sock_opt) != PR_SUCCESS) + return nss_fail_connect(connssl, data, CURLE_SSL_CONNECT_ERROR); +@@ -1615,16 +1616,14 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, + /* 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; + } + ++ /* enable/disable blocking mode before handshake */ ++ rv = nss_set_blocking(connssl, data, blocking); ++ if(rv) ++ return rv; ++ + rv = nss_do_connect(conn, sockindex); + switch(rv) { + case CURLE_OK: +@@ -1640,7 +1639,7 @@ static CURLcode nss_connect_common(struct connectdata *conn, int sockindex, + + if(blocking) { + /* in blocking mode, set NSS non-blocking mode _after_ SSL handshake */ +- rv = nss_set_nonblock(connssl, data); ++ rv = nss_set_blocking(connssl, data, /* blocking */ FALSE); + if(rv) + return rv; + } +-- +2.7.4 + + +From 9dbd6550acdc143da0b044ae3b06368a87c8449a Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 27 Mar 2017 18:00:44 +0200 +Subject: [PATCH 6/7] url: plug memory leaks triggered by + curl-7_37_1-19-ga4cece3 + +--- + lib/url.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/lib/url.c b/lib/url.c +index cfc2744..ed72be1 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -421,6 +421,7 @@ CURLcode Curl_close(struct SessionHandle *data) + data->state.path = NULL; + + Curl_safefree(data->state.proto.generic); ++ Curl_safefree(data->req.newurl); + + /* Close down all open SSL info and sessions */ + Curl_ssl_close_all(data); +@@ -3923,6 +3924,14 @@ static CURLcode setup_connection_internals(struct connectdata *conn) + const struct Curl_handler * p; + CURLcode result; + ++ /* XXX: picked from curl-7_32_0-2-g4ad8e14 */ ++ /* in some case in the multi state-machine, we go back to the CONNECT state ++ and then a second (or third or...) call to this function will be made ++ without doing a DISCONNECT or DONE in between (since the connection is ++ yet in place) and therefore this function needs to first make sure ++ there's no lingering previous data allocated. */ ++ Curl_safefree(conn->data->req.newurl); ++ + conn->socktype = SOCK_STREAM; /* most of them are TCP streams */ + + /* Scan protocol handler table. */ +-- +2.9.3 + + +From cfb58b02f5bb78a2f4b17f3bb6ce6acd196b3ec6 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Tue, 28 Mar 2017 15:50:59 +0200 +Subject: [PATCH 7/7] http: do not treat FTPS over CONNECT as HTTPS + +If we use FTPS over CONNECT, the TLS handshake for the FTPS control +connection needs to be initiated in the SENDPROTOCONNECT state, not +the WAITPROXYCONNECT state. Otherwise, if the TLS handshake completed +without blocking, the information about the completed TLS handshake +would be saved to a wrong flag. Consequently, the TLS handshake would +be initiated in the SENDPROTOCONNECT state once again on the same +connection, resulting in a failure of the TLS handshake. I was able to +observe the failure with the NSS backend if curl ran through valgrind. + +Note that this commit partially reverts curl-7_21_6-52-ge34131d. + +Upstream-commit: 2549831daaa3aef394f7b42e750cba1afae35642 +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 04beeb1..db37cf9 100644 +--- a/lib/http.c ++++ b/lib/http.c +@@ -1310,7 +1310,7 @@ CURLcode Curl_http_connect(struct connectdata *conn, bool *done) + /* nothing else to do except wait right now - we're not done here. */ + return CURLE_OK; + +- if(conn->given->flags & PROTOPT_SSL) { ++ if(conn->given->protocol & CURLPROTO_HTTPS) { + /* perform SSL initialization */ + result = https_connecting(conn, done); + if(result) +-- +2.9.3 + diff --git a/SOURCES/0050-curl-7.29.0-3a5d5de9.patch b/SOURCES/0050-curl-7.29.0-3a5d5de9.patch new file mode 100644 index 0000000..d905cda --- /dev/null +++ b/SOURCES/0050-curl-7.29.0-3a5d5de9.patch @@ -0,0 +1,132 @@ +From 49d801727856998cf6230f1a18d971649376d5a7 Mon Sep 17 00:00:00 2001 +From: Peter Wang +Date: Fri, 26 Aug 2016 16:28:39 +1000 +Subject: [PATCH 1/2] nss: work around race condition in PK11_FindSlotByName() + +Serialise the call to PK11_FindSlotByName() to avoid spurious errors in +a multi-threaded environment. The underlying cause is a race condition +in nssSlot_IsTokenPresent(). + +Bug: https://bugzilla.mozilla.org/1297397 + +Closes #985 + +Upstream-commit: 3a5d5de9ef52ebe8ca2bda2165edc1b34c242e54 +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 26 +++++++++++++++++++++----- + 1 file changed, 21 insertions(+), 5 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index cf45f3a..3f88ea7 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -74,8 +74,9 @@ + + PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd); + +-PRLock * nss_initlock = NULL; +-PRLock * nss_crllock = NULL; ++static PRLock *nss_initlock = NULL; ++static PRLock *nss_crllock = NULL; ++static PRLock *nss_findslot_lock = NULL; + NSSInitContext * nss_context = NULL; + + volatile int initialized = 0; +@@ -347,6 +348,19 @@ static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind) + return NULL; + } + ++/* Lock/unlock wrapper for PK11_FindSlotByName() to work around race condition ++ * in nssSlot_IsTokenPresent() causing spurious SEC_ERROR_NO_TOKEN. For more ++ * details, go to . ++ */ ++static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name) ++{ ++ PK11SlotInfo *slot; ++ PR_Lock(nss_initlock); ++ slot = PK11_FindSlotByName(slot_name); ++ PR_Unlock(nss_initlock); ++ return slot; ++} ++ + /* Call PK11_CreateGenericObject() with the given obj_class and filename. If + * the call succeeds, append the object handle to the list of objects so that + * the object can be destroyed in Curl_nss_close(). */ +@@ -369,7 +383,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl, + if(!slot_name) + return CURLE_OUT_OF_MEMORY; + +- slot = PK11_FindSlotByName(slot_name); ++ slot = nss_find_slot_by_name(slot_name); + free(slot_name); + if(!slot) + return err; +@@ -549,7 +563,7 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex, + return rv; + } + +- slot = PK11_FindSlotByName("PEM Token #1"); ++ slot = nss_find_slot_by_name("PEM Token #1"); + if(!slot) + return CURLE_SSL_CERTPROBLEM; + +@@ -788,7 +802,7 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, + struct CERTCertificateStr *cert; + struct SECKEYPrivateKeyStr *key; + +- PK11SlotInfo *slot = PK11_FindSlotByName(pem_slotname); ++ PK11SlotInfo *slot = nss_find_slot_by_name(pem_slotname); + if(NULL == slot) { + failf(data, "NSS: PK11 slot not found: %s", pem_slotname); + return SECFailure; +@@ -1017,6 +1031,7 @@ int Curl_nss_init(void) + PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256); + nss_initlock = PR_NewLock(); + nss_crllock = PR_NewLock(); ++ nss_findslot_lock = PR_NewLock(); + } + + /* We will actually initialize NSS later */ +@@ -1064,6 +1079,7 @@ void Curl_nss_cleanup(void) + + PR_DestroyLock(nss_initlock); + PR_DestroyLock(nss_crllock); ++ PR_DestroyLock(nss_findslot_lock); + nss_initlock = NULL; + + initialized = 0; +-- +2.9.3 + + +From 610ca3bc8549cf907147b22c67c0062225ec58a7 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Sun, 15 Jan 2017 13:10:43 +0100 +Subject: [PATCH 2/2] nss: use the correct lock in nss_find_slot_by_name() + +Upstream-commit: 25ed9ea51257c0561237d1b725c4ff3d59b3f32c +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 3f88ea7..9e0e373 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -355,9 +355,9 @@ static char* dup_nickname(struct SessionHandle *data, enum dupstring cert_kind) + static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name) + { + PK11SlotInfo *slot; +- PR_Lock(nss_initlock); ++ PR_Lock(nss_findslot_lock); + slot = PK11_FindSlotByName(slot_name); +- PR_Unlock(nss_initlock); ++ PR_Unlock(nss_findslot_lock); + return slot; + } + +-- +2.9.3 + diff --git a/SOURCES/0109-curl-7.29.0-crl-valgrind.patch b/SOURCES/0109-curl-7.29.0-crl-valgrind.patch new file mode 100644 index 0000000..7e02ce4 --- /dev/null +++ b/SOURCES/0109-curl-7.29.0-crl-valgrind.patch @@ -0,0 +1,25 @@ +From 1442501b9eee46a959f3480600e2a63c831e9d9e Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 1 Mar 2017 15:11:34 +0100 +Subject: [PATCH] test313: suppress a bug newly detected by valgrind (#1427883) + +--- + tests/data/test313 | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/tests/data/test313 b/tests/data/test313 +index c54495a..aada83c 100644 +--- a/tests/data/test313 ++++ b/tests/data/test313 +@@ -35,5 +35,8 @@ perl -e "print 'Test requires default test server host' if ( '%HOSTIP' ne '127.0 + + 60 + ++ ++disable ++ + + +-- +2.9.3 + diff --git a/SPECS/curl.spec b/SPECS/curl.spec index e591f0c..e89db35 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: 35%{?dist} +Release: 42%{?dist} License: MIT Group: Applications/Internet Source: http://curl.haxx.se/download/%{name}-%{version}.tar.lzma @@ -136,6 +136,27 @@ Patch42: 0042-curl-7.29.0-CVE-2016-5419.patch # fix re-using connections with wrong client cert (CVE-2016-5420) Patch43: 0043-curl-7.29.0-CVE-2016-5420.patch +# reject negative string lengths in curl_easy_[un]escape() (CVE-2016-7167) +Patch44: 0044-curl-7.29.0-CVE-2016-7167.patch + +# curl -E: allow to escape ':' in cert nickname (#1376062) +Patch45: 0045-curl-7.29.0-865d4138.patch + +# make libcurl recognize chacha20-poly1305 and SHA384 cipher-suites (#1374740) +Patch46: 0046-curl-7.29.0-049aa925.patch + +# handle cookies with numerical IPv6 address (#1341503) +Patch47: 0047-curl-7.29.0-85b9dc80.patch + +# fix tight loop in non-blocking TLS handhsake over proxy (#1388162) +Patch48: 0048-curl-7.29.0-eb84412b.patch + +# make FTPS work with --proxytunnel (#1420327) +Patch49: 0049-curl-7.29.0-8fa54098.patch + +# work around race condition in PK11_FindSlotByName() in NSS (#1404815) +Patch50: 0050-curl-7.29.0-3a5d5de9.patch + # patch making libcurl multilib ready Patch101: 0101-curl-7.29.0-multilib.patch @@ -161,9 +182,13 @@ Patch107: 0107-curl-7.21.4-libidn-valgrind.patch # a simple iconv can't fix them Patch108: 0108-curl-7.29.0-utf8.patch +# test313: suppress a bug newly detected by valgrind (#1427883) +Patch109: 0109-curl-7.29.0-crl-valgrind.patch + Provides: webclient URL: http://curl.haxx.se/ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(id -nu) +BuildRequires: automake BuildRequires: groff BuildRequires: krb5-devel BuildRequires: libidn-devel @@ -300,17 +325,32 @@ documentation of the library, too. %patch106 -p1 %patch107 -p1 %patch108 -p1 +%patch109 -p1 # upstream patches %patch41 -p1 %patch42 -p1 %patch43 -p1 +%patch44 -p1 +%patch45 -p1 +%patch46 -p1 +%patch47 -p1 +%patch48 -p1 +%patch49 -p1 +%patch50 -p1 + +# regenerate Makefile.in files +aclocal -I m4 +automake # replace hard wired port numbers in the test suite cd tests/data/ sed -i s/899\\\([0-9]\\\)/%{?__isa_bits}9\\1/ test* cd - +# avoid spurious failure of test1086 on s390(x) builders (#1072273) +sed -i 's/-m 7/-m 15/' tests/data/test1086 + # disable test 1112 (#565305) and test 2032 (#1241168) printf "1112\n2032\n" >> tests/data/DISABLED @@ -347,8 +387,7 @@ LD_LIBRARY_PATH=$RPM_BUILD_ROOT%{_libdir} export LD_LIBRARY_PATH # uncomment to use the non-stripped library in tests -# LD_PRELOAD=`find -name \*.so` -# LD_PRELOAD=`readlink -f $LD_PRELOAD` +# LD_LIBRARY_PATH=$(dirname $(realpath $(find -name \*.so))) cd tests make %{?_smp_mflags} @@ -414,6 +453,31 @@ rm -rf $RPM_BUILD_ROOT %{_datadir}/aclocal/libcurl.m4 %changelog +* Wed Mar 29 2017 Kamil Dudka 7.29.0-42 +- fix use of uninitialized variable detected by Covscan + +* Wed Mar 29 2017 Kamil Dudka 7.29.0-41 +- make FTPS work with --proxytunnel (#1420327) + +* Mon Mar 27 2017 Kamil Dudka 7.29.0-40 +- make FTPS work with --proxytunnel (#1420327) + +* Wed Mar 01 2017 Kamil Dudka 7.29.0-39 +- work around race condition in PK11_FindSlotByName() in NSS (#1404815) + +* Thu Feb 09 2017 Kamil Dudka 7.29.0-38 +- make FTPS work with --proxytunnel (#1420327) + +* Thu Oct 06 2016 Kamil Dudka 7.29.0-37 +- fix tight loop in non-blocking TLS handhsake over proxy (#1388162) +- handle cookies with numerical IPv6 address (#1341503) +- make libcurl recognize chacha20-poly1305 and SHA384 cipher-suites (#1374740) +- curl -E: allow to escape ':' in cert nickname (#1376062) +- run automake in %%prep to avoid patching Makefile.in files from now on + +* Tue Sep 20 2016 Kamil Dudka 7.29.0-36 +- reject negative string lengths in curl_easy_[un]escape() (CVE-2016-7167) + * Fri Aug 26 2016 Kamil Dudka 7.29.0-35 - fix incorrect use of a previously loaded certificate from file (related to CVE-2016-5420)