diff --git a/.curl.metadata b/.curl.metadata new file mode 100644 index 0000000..bb1ea73 --- /dev/null +++ b/.curl.metadata @@ -0,0 +1 @@ +28f2ffe1a4eb5b8d0fb95db1b2ef6ba04e2572fe SOURCES/curl-7.29.0.tar.lzma diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d50d4a3 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/curl-7.29.0.tar.lzma diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/0001-curl-7.29.0-da3fc1ee.patch b/SOURCES/0001-curl-7.29.0-da3fc1ee.patch new file mode 100644 index 0000000..bebcb95 --- /dev/null +++ b/SOURCES/0001-curl-7.29.0-da3fc1ee.patch @@ -0,0 +1,321 @@ +From 48b69def52771149ed19189284b8c6d1ba667ef7 Mon Sep 17 00:00:00 2001 +From: Linus Nielsen Feltzing +Date: Sun, 10 Feb 2013 22:57:58 +0100 +Subject: [PATCH] Fix NULL pointer reference when closing an unused multi handle. + +[upstream commit da3fc1ee91de656a30f3a12de394bcba55119872] + +Signed-off-by: Kamil Dudka +--- + lib/multi.c | 8 +++-- + tests/data/Makefile.am | 2 +- + tests/data/Makefile.in | 2 +- + tests/data/test1508 | 31 +++++++++++++++++ + tests/libtest/Makefile.in | 79 ++++++++++++++++++++++++++++++++++++++++++-- + tests/libtest/Makefile.inc | 6 +++- + tests/libtest/lib1508.c | 49 +++++++++++++++++++++++++++ + 7 files changed, 168 insertions(+), 9 deletions(-) + create mode 100644 tests/data/test1508 + create mode 100644 tests/libtest/lib1508.c + +diff --git a/lib/multi.c b/lib/multi.c +index fa0afb9..706df23 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -1773,10 +1773,12 @@ CURLMcode curl_multi_cleanup(CURLM *multi_handle) + /* Close all the connections in the connection cache */ + close_all_connections(multi); + +- multi->closure_handle->dns.hostcache = multi->hostcache; +- Curl_hostcache_clean(multi->closure_handle); ++ if(multi->closure_handle) { ++ multi->closure_handle->dns.hostcache = multi->hostcache; ++ Curl_hostcache_clean(multi->closure_handle); + +- Curl_close(multi->closure_handle); ++ Curl_close(multi->closure_handle); ++ } + multi->closure_handle = NULL; + + Curl_hash_destroy(multi->sockhash); +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index d82534d..9f569a3 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -93,7 +93,7 @@ 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 \ +-test1500 test1501 test1502 test1503 test1504 test1505 test1506 \ ++test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1508 \ + 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 df52421..d5b0918 100644 +--- a/tests/data/Makefile.in ++++ b/tests/data/Makefile.in +@@ -357,7 +357,7 @@ 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 \ +-test1500 test1501 test1502 test1503 test1504 test1505 test1506 \ ++test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1508 \ + 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/test1508 b/tests/data/test1508 +new file mode 100644 +index 0000000..f8607e5 +--- /dev/null ++++ b/tests/data/test1508 +@@ -0,0 +1,31 @@ ++ ++ ++ ++HTTP ++multi ++ ++ ++ ++# Client-side ++ ++ ++none ++ ++ ++lib1508 ++ ++ ++Close a multi handle without using it ++ ++ ++http://%HOSTIP:%HTTPPORT/path/1508 ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++We are done ++ ++ ++ +diff --git a/tests/libtest/Makefile.in b/tests/libtest/Makefile.in +index 406b457..7683c09 100644 +--- a/tests/libtest/Makefile.in ++++ b/tests/libtest/Makefile.in +@@ -85,7 +85,7 @@ noinst_PROGRAMS = chkhostname$(EXEEXT) libauthretry$(EXEEXT) \ + lib591$(EXEEXT) lib597$(EXEEXT) lib598$(EXEEXT) \ + lib599$(EXEEXT) lib1500$(EXEEXT) lib1501$(EXEEXT) \ + lib1502$(EXEEXT) lib1503$(EXEEXT) lib1504$(EXEEXT) \ +- lib1505$(EXEEXT) lib1506$(EXEEXT) ++ lib1505$(EXEEXT) lib1506$(EXEEXT) lib1508$(EXEEXT) + subdir = tests/libtest + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 + am__aclocal_m4_deps = $(top_srcdir)/m4/curl-compilers.m4 \ +@@ -173,6 +173,13 @@ am_lib1506_OBJECTS = lib1506-lib1506.$(OBJEXT) $(am__objects_18) \ + $(am__objects_19) $(am__objects_20) + lib1506_OBJECTS = $(am_lib1506_OBJECTS) + lib1506_DEPENDENCIES = $(am__DEPENDENCIES_1) ++am__objects_151 = lib1508-first.$(OBJEXT) ++am__objects_152 = lib1508-testutil.$(OBJEXT) ++am__objects_153 = lib1508-warnless.$(OBJEXT) ++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_21 = lib500-first.$(OBJEXT) + am__objects_22 = lib500-testutil.$(OBJEXT) + am__objects_23 = lib500-testtrace.$(OBJEXT) +@@ -632,7 +639,7 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + SOURCES = $(libhostname_la_SOURCES) $(chkhostname_SOURCES) \ + $(lib1500_SOURCES) $(lib1501_SOURCES) $(lib1502_SOURCES) \ + $(lib1503_SOURCES) $(lib1504_SOURCES) $(lib1505_SOURCES) \ +- $(lib1506_SOURCES) $(lib500_SOURCES) $(lib501_SOURCES) \ ++ $(lib1506_SOURCES) $(lib1508_SOURCES) $(lib500_SOURCES) $(lib501_SOURCES) \ + $(lib502_SOURCES) $(lib503_SOURCES) $(lib504_SOURCES) \ + $(lib505_SOURCES) $(lib506_SOURCES) $(lib507_SOURCES) \ + $(lib508_SOURCES) $(lib510_SOURCES) $(lib511_SOURCES) \ +@@ -662,7 +669,7 @@ SOURCES = $(libhostname_la_SOURCES) $(chkhostname_SOURCES) \ + DIST_SOURCES = $(libhostname_la_SOURCES) $(chkhostname_SOURCES) \ + $(lib1500_SOURCES) $(lib1501_SOURCES) $(lib1502_SOURCES) \ + $(lib1503_SOURCES) $(lib1504_SOURCES) $(lib1505_SOURCES) \ +- $(lib1506_SOURCES) $(lib500_SOURCES) $(lib501_SOURCES) \ ++ $(lib1506_SOURCES) $(lib1508_SOURCES) $(lib500_SOURCES) $(lib501_SOURCES) \ + $(lib502_SOURCES) $(lib503_SOURCES) $(lib504_SOURCES) \ + $(lib505_SOURCES) $(lib506_SOURCES) $(lib507_SOURCES) \ + $(lib508_SOURCES) $(lib510_SOURCES) $(lib511_SOURCES) \ +@@ -1155,6 +1162,9 @@ lib1505_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1505 + lib1506_SOURCES = lib1506.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) + lib1506_LDADD = $(TESTUTIL_LIBS) + lib1506_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1506 ++lib1508_SOURCES = lib1508.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) ++lib1508_LDADD = $(TESTUTIL_LIBS) ++lib1508_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1508 + @BUILD_LIBHOSTNAME_FALSE@noinst_LTLIBRARIES = + + # Makefile.inc provides the source defines (TESTUTIL, SUPPORTFILES, +@@ -1253,6 +1263,9 @@ lib1505$(EXEEXT): $(lib1505_OBJECTS) $(lib1505_DEPENDENCIES) $(EXTRA_lib1505_DEP + lib1506$(EXEEXT): $(lib1506_OBJECTS) $(lib1506_DEPENDENCIES) $(EXTRA_lib1506_DEPENDENCIES) + @rm -f lib1506$(EXEEXT) + $(LINK) $(lib1506_OBJECTS) $(lib1506_LDADD) $(LIBS) ++lib1508$(EXEEXT): $(lib1508_OBJECTS) $(lib1508_DEPENDENCIES) $(EXTRA_lib1508_DEPENDENCIES) ++ @rm -f lib1508$(EXEEXT) ++ $(LINK) $(lib1508_OBJECTS) $(lib1508_LDADD) $(LIBS) + lib500$(EXEEXT): $(lib500_OBJECTS) $(lib500_DEPENDENCIES) $(EXTRA_lib500_DEPENDENCIES) + @rm -f lib500$(EXEEXT) + $(LINK) $(lib500_OBJECTS) $(lib500_LDADD) $(LIBS) +@@ -1520,6 +1533,10 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1506-lib1506.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1506-testutil.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1506-warnless.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1508-first.Po@am__quote@ ++@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)/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@ +@@ -2163,6 +2180,62 @@ lib1506-warnless.obj: ../../lib/warnless.c + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1506_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1506-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi` + ++lib1508-lib1508.o: lib1508.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1508_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1508-lib1508.o -MD -MP -MF $(DEPDIR)/lib1508-lib1508.Tpo -c -o lib1508-lib1508.o `test -f 'lib1508.c' || echo '$(srcdir)/'`lib1508.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1508-lib1508.Tpo $(DEPDIR)/lib1508-lib1508.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lib1508.c' object='lib1508-lib1508.o' libtool=no @AMDEPBACKSLASH@ ++@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-lib1508.o `test -f 'lib1508.c' || echo '$(srcdir)/'`lib1508.c ++ ++lib1508-lib1508.obj: lib1508.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1508_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1508-lib1508.obj -MD -MP -MF $(DEPDIR)/lib1508-lib1508.Tpo -c -o lib1508-lib1508.obj `if test -f 'lib1508.c'; then $(CYGPATH_W) 'lib1508.c'; else $(CYGPATH_W) '$(srcdir)/lib1508.c'; fi` ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1508-lib1508.Tpo $(DEPDIR)/lib1508-lib1508.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lib1508.c' object='lib1508-lib1508.obj' libtool=no @AMDEPBACKSLASH@ ++@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-lib1508.obj `if test -f 'lib1508.c'; then $(CYGPATH_W) 'lib1508.c'; else $(CYGPATH_W) '$(srcdir)/lib1508.c'; fi` ++ ++lib1508-first.o: first.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1508_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1508-first.o -MD -MP -MF $(DEPDIR)/lib1508-first.Tpo -c -o lib1508-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1508-first.Tpo $(DEPDIR)/lib1508-first.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='first.c' object='lib1508-first.o' libtool=no @AMDEPBACKSLASH@ ++@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-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c ++ ++lib1508-first.obj: first.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1508_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1508-first.obj -MD -MP -MF $(DEPDIR)/lib1508-first.Tpo -c -o lib1508-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi` ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1508-first.Tpo $(DEPDIR)/lib1508-first.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='first.c' object='lib1508-first.obj' libtool=no @AMDEPBACKSLASH@ ++@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-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi` ++ ++lib1508-testutil.o: testutil.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1508_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1508-testutil.o -MD -MP -MF $(DEPDIR)/lib1508-testutil.Tpo -c -o lib1508-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1508-testutil.Tpo $(DEPDIR)/lib1508-testutil.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='testutil.c' object='lib1508-testutil.o' libtool=no @AMDEPBACKSLASH@ ++@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-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c ++ ++lib1508-testutil.obj: testutil.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1508_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1508-testutil.obj -MD -MP -MF $(DEPDIR)/lib1508-testutil.Tpo -c -o lib1508-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi` ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1508-testutil.Tpo $(DEPDIR)/lib1508-testutil.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='testutil.c' object='lib1508-testutil.obj' libtool=no @AMDEPBACKSLASH@ ++@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-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi` ++ ++lib1508-warnless.o: ../../lib/warnless.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1508_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1508-warnless.o -MD -MP -MF $(DEPDIR)/lib1508-warnless.Tpo -c -o lib1508-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1508-warnless.Tpo $(DEPDIR)/lib1508-warnless.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../lib/warnless.c' object='lib1508-warnless.o' libtool=no @AMDEPBACKSLASH@ ++@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.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c ++ ++lib1508-warnless.obj: ../../lib/warnless.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1508_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1508-warnless.obj -MD -MP -MF $(DEPDIR)/lib1508-warnless.Tpo -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` ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1508-warnless.Tpo $(DEPDIR)/lib1508-warnless.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../lib/warnless.c' object='lib1508-warnless.obj' libtool=no @AMDEPBACKSLASH@ ++@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` ++ + 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 82c265d..8bf2be4 100644 +--- a/tests/libtest/Makefile.inc ++++ b/tests/libtest/Makefile.inc +@@ -23,7 +23,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \ + lib582 lib583 lib585 lib586 lib587 \ + lib590 lib591 lib597 lib598 lib599 \ + \ +- lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 ++ lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1508 + + chkhostname_SOURCES = chkhostname.c ../../lib/curl_gethostname.c + chkhostname_LDADD = @CURL_NETWORK_LIBS@ +@@ -312,3 +312,7 @@ lib1505_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1505 + lib1506_SOURCES = lib1506.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) + lib1506_LDADD = $(TESTUTIL_LIBS) + lib1506_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1506 ++ ++lib1508_SOURCES = lib1508.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) ++lib1508_LDADD = $(TESTUTIL_LIBS) ++lib1508_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1508 +diff --git a/tests/libtest/lib1508.c b/tests/libtest/lib1508.c +new file mode 100644 +index 0000000..72f26d1 +--- /dev/null ++++ b/tests/libtest/lib1508.c +@@ -0,0 +1,49 @@ ++/*************************************************************************** ++ * _ _ ____ _ ++ * Project ___| | | | _ \| | ++ * / __| | | | |_) | | ++ * | (__| |_| | _ <| |___ ++ * \___|\___/|_| \_\_____| ++ * ++ * Copyright (C) 2013, Linus Nielsen Feltzing ++ * ++ * 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 "testutil.h" ++#include "warnless.h" ++#include "memdebug.h" ++ ++int test(char *URL) ++{ ++ int res = 0; ++ CURLM *m = NULL; ++ ++ (void)URL; ++ ++ global_init(CURL_GLOBAL_ALL); ++ ++ multi_init(m); ++ ++test_cleanup: ++ ++ /* proper cleanup sequence - type PB */ ++ ++ curl_multi_cleanup(m); ++ curl_global_cleanup(); ++ ++ printf("We are done\n"); ++ ++ return res; ++} +-- +1.7.1 + diff --git a/SOURCES/0002-curl-7.29.0-9d0af301.patch b/SOURCES/0002-curl-7.29.0-9d0af301.patch new file mode 100644 index 0000000..0b9f7aa --- /dev/null +++ b/SOURCES/0002-curl-7.29.0-9d0af301.patch @@ -0,0 +1,47 @@ +From 8d25353ae1661ce50fe564e733f3ef45004f4bdf Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Tue, 5 Mar 2013 17:51:01 +0100 +Subject: [PATCH] nss: fix misplaced code enabling non-blocking socket mode + +The option needs to be set on the SSL socket. Setting it on the model +takes no effect. Note that the non-blocking mode is still not enabled +for the handshake because the code is not yet ready for that. + +[upstream commit 9d0af3018c5db25f5adda216dbcad6056b4a3107] +--- + lib/nss.c | 12 ++++++------ + 1 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 8a2cb09..a2c5c63 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1237,12 +1237,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + goto error; + model = SSL_ImportFD(NULL, model); + +- /* make the socket nonblocking */ +- sock_opt.option = PR_SockOpt_Nonblocking; +- sock_opt.value.non_blocking = PR_TRUE; +- if(PR_SetSocketOption(model, &sock_opt) != PR_SUCCESS) +- goto error; +- + if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess) + goto error; + if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess) +@@ -1415,6 +1409,12 @@ 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; +-- +1.7.1 + diff --git a/SOURCES/0003-curl-7.29.0-491e026c.patch b/SOURCES/0003-curl-7.29.0-491e026c.patch new file mode 100644 index 0000000..c136e34 --- /dev/null +++ b/SOURCES/0003-curl-7.29.0-491e026c.patch @@ -0,0 +1,39 @@ +From a2e6eadf6a72f7587eb9bc1ad52383e4c5507b12 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 11 Mar 2013 16:57:25 +0100 +Subject: [PATCH 1/2] easy: do not ignore poll() failures other than EINTR + +[upstream commit 491e026ccda0e60975fa6e2e9cf3ccca37e18f7b] +--- + lib/easy.c | 12 ++++++++++-- + 1 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/lib/easy.c b/lib/easy.c +index c27deff..2e747bb 100644 +--- a/lib/easy.c ++++ b/lib/easy.c +@@ -441,11 +441,19 @@ CURLcode curl_easy_perform(CURL *easy) + + while(!done && !mcode) { + int still_running; ++ int ret; + +- mcode = curl_multi_wait(multi, NULL, 0, 1000, NULL); ++ mcode = curl_multi_wait(multi, NULL, 0, 1000, &ret); ++ ++ if(mcode == CURLM_OK) { ++ if(ret == -1) { ++ /* poll() failed not on EINTR, indicate a network problem */ ++ code = CURLE_RECV_ERROR; ++ break; ++ } + +- if(mcode == CURLM_OK) + mcode = curl_multi_perform(multi, &still_running); ++ } + + /* only read 'still_running' if curl_multi_perform() return OK */ + if((mcode == CURLM_OK) && !still_running) { +-- +1.7.1 + diff --git a/SOURCES/0004-curl-7.29.0-57ccdfa8.patch b/SOURCES/0004-curl-7.29.0-57ccdfa8.patch new file mode 100644 index 0000000..1448d64 --- /dev/null +++ b/SOURCES/0004-curl-7.29.0-57ccdfa8.patch @@ -0,0 +1,143 @@ +From 37a515d9933a3160a8a868d5a697a42b28f6d792 Mon Sep 17 00:00:00 2001 +From: Zdenek Pavlas +Date: Mon, 11 Mar 2013 14:57:07 +0100 +Subject: [PATCH 2/2] curl_global_init: accept the CURL_GLOBAL_ACK_EINTR flag + +The flag can be used in pycurl-based applications where using the multi +interface would not be acceptable because of the performance lost caused +by implementing the select() loop in python. + +Bug: http://curl.haxx.se/bug/view.cgi?id=1168 +Downstream Bug: https://bugzilla.redhat.com/919127 + +[upstream commit 57ccdfa8d2bb6275388223f4676cd623ebd01697] +--- + docs/libcurl/curl_global_init.3 | 4 ++++ + docs/libcurl/symbols-in-versions | 1 + + include/curl/curl.h | 1 + + lib/easy.c | 2 ++ + lib/select.c | 17 ++--------------- + lib/select.h | 6 ++++++ + 6 files changed, 16 insertions(+), 15 deletions(-) + +diff --git a/docs/libcurl/curl_global_init.3 b/docs/libcurl/curl_global_init.3 +index d91e1bd..6a08383 100644 +--- a/docs/libcurl/curl_global_init.3 ++++ b/docs/libcurl/curl_global_init.3 +@@ -70,6 +70,10 @@ Initialise nothing extra. This sets no bit. + .B CURL_GLOBAL_DEFAULT + A sensible default. It will init both SSL and Win32. Right now, this equals + the functionality of the \fBCURL_GLOBAL_ALL\fP mask. ++.TP ++.B CURL_GLOBAL_ACK_EINTR ++When this flag is set, curl will acknowledge EINTR condition when connecting ++or when waiting for data. Otherwise, curl waits until full timeout elapses. + .SH RETURN VALUE + If this function returns non-zero, something went wrong and you cannot use the + other curl functions. +diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions +index 1de1ace..37b5e27 100644 +--- a/docs/libcurl/symbols-in-versions ++++ b/docs/libcurl/symbols-in-versions +@@ -614,6 +614,7 @@ CURL_GLOBAL_DEFAULT 7.8 + CURL_GLOBAL_NOTHING 7.8 + CURL_GLOBAL_SSL 7.8 + CURL_GLOBAL_WIN32 7.8.1 ++CURL_GLOBAL_ACK_EINTR 7.30.0 + CURL_HTTP_VERSION_1_0 7.9.1 + CURL_HTTP_VERSION_1_1 7.9.1 + CURL_HTTP_VERSION_NONE 7.9.1 +diff --git a/include/curl/curl.h b/include/curl/curl.h +index 5b39a24..80e4cf5 100644 +--- a/include/curl/curl.h ++++ b/include/curl/curl.h +@@ -2023,6 +2023,7 @@ typedef enum { + #define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) + #define CURL_GLOBAL_NOTHING 0 + #define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL ++#define CURL_GLOBAL_ACK_EINTR (1<<2) + + + /***************************************************************************** +diff --git a/lib/easy.c b/lib/easy.c +index 2e747bb..2739598 100644 +--- a/lib/easy.c ++++ b/lib/easy.c +@@ -262,6 +262,8 @@ CURLcode curl_global_init(long flags) + } + #endif + ++ Curl_ack_eintr = flags & CURL_GLOBAL_ACK_EINTR; ++ + init_flags = flags; + + /* Preset pseudo-random number sequence. */ +diff --git a/lib/select.c b/lib/select.c +index d13e122..db7fb6d 100644 +--- a/lib/select.c ++++ b/lib/select.c +@@ -50,11 +50,8 @@ + + #define elapsed_ms (int)curlx_tvdiff(curlx_tvnow(), initial_tv) + +-#ifdef CURL_ACKNOWLEDGE_EINTR +-#define error_not_EINTR (1) +-#else +-#define error_not_EINTR (error != EINTR) +-#endif ++int Curl_ack_eintr = 0; ++#define error_not_EINTR (Curl_ack_eintr || error != EINTR) + + /* + * Internal function used for waiting a specific amount of ms +@@ -67,10 +64,6 @@ + * Timeout resolution, accuracy, as well as maximum supported + * value is system dependent, neither factor is a citical issue + * for the intended use of this function in the library. +- * On non-DOS and non-Winsock platforms, when compiled with +- * CURL_ACKNOWLEDGE_EINTR defined, EINTR condition is honored +- * and function might exit early without awaiting full timeout, +- * otherwise EINTR will be ignored and full timeout will elapse. + * + * Return values: + * -1 = system call error, invalid timeout value, or interrupted +@@ -133,9 +126,6 @@ int Curl_wait_ms(int timeout_ms) + * A negative timeout value makes this function wait indefinitely, + * unles no valid file descriptor is given, when this happens the + * negative timeout is ignored and the function times out immediately. +- * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition +- * is honored and function might exit early without awaiting timeout, +- * otherwise EINTR will be ignored. + * + * Return values: + * -1 = system call error or fd >= FD_SETSIZE +@@ -351,9 +341,6 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ + * A negative timeout value makes this function wait indefinitely, + * unles no valid file descriptor is given, when this happens the + * negative timeout is ignored and the function times out immediately. +- * When compiled with CURL_ACKNOWLEDGE_EINTR defined, EINTR condition +- * is honored and function might exit early without awaiting timeout, +- * otherwise EINTR will be ignored. + * + * Return values: + * -1 = system call error or fd >= FD_SETSIZE +diff --git a/lib/select.h b/lib/select.h +index 00789bb..c00afe1 100644 +--- a/lib/select.h ++++ b/lib/select.h +@@ -81,6 +81,12 @@ int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, + + int Curl_poll(struct pollfd ufds[], unsigned int nfds, int timeout_ms); + ++/* On non-DOS and non-Winsock platforms, when Curl_ack_eintr is set, ++ * EINTR condition is honored and function might exit early without ++ * awaiting full timeout. Otherwise EINTR will be ignored and full ++ * timeout will elapse. */ ++extern int Curl_ack_eintr; ++ + int Curl_wait_ms(int timeout_ms); + + #ifdef TPF +-- +1.7.1 + diff --git a/SOURCES/0005-curl-7.29.0-2eb8dcf2.patch b/SOURCES/0005-curl-7.29.0-2eb8dcf2.patch new file mode 100644 index 0000000..d0fbbce --- /dev/null +++ b/SOURCES/0005-curl-7.29.0-2eb8dcf2.patch @@ -0,0 +1,295 @@ +From 0b7dd36575821bd6e4e86f7b51ac001e69abddf9 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 12 Apr 2013 15:53:39 +0200 +Subject: [PATCH 1/3] test1216: test tailmatching cookie domains + +This test is an attempt to repeat the problem YAMADA Yasuharu reported +at http://curl.haxx.se/mail/lib-2013-04/0108.html + +Conflicts: + + tests/data/Makefile.am + +Signed-off-by: Kamil Dudka +--- + tests/data/Makefile.am | 2 +- + tests/data/Makefile.in | 2 +- + tests/data/test1216 | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 64 insertions(+), 2 deletions(-) + create mode 100644 tests/data/test1216 + +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 9f569a3..d714e5d 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 \ ++test1208 test1209 test1210 test1211 test1216 \ + test1220 test1221 test1222 test1223 \ + 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 d5b0918..a070266 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 \ ++test1208 test1209 test1210 test1211 test1216 \ + test1220 test1221 test1222 test1223 \ + test1300 test1301 test1302 test1303 test1304 test1305 \ + test1306 test1307 test1308 test1309 test1310 test1311 test1312 test1313 \ +diff --git a/tests/data/test1216 b/tests/data/test1216 +new file mode 100644 +index 0000000..e63fe92 +--- /dev/null ++++ b/tests/data/test1216 +@@ -0,0 +1,62 @@ ++ ++ ++ ++HTTP ++HTTP GET ++HTTP proxy ++cookies ++ ++ ++ ++# Server-side ++ ++ ++HTTP/1.1 200 OK ++Server: Microsoft-IIS/4.0 ++Date: Tue, 25 Sep 2001 19:37:44 GMT ++Content-Type: text/html ++Connection: close ++Content-Length: 21 ++ ++This server says moo ++ ++ ++ ++# Client-side ++ ++ ++http ++ ++ ++HTTP cookie domains tailmatching the host name ++ ++ ++http://example.fake/c/1216 http://bexample.fake/c/1216 -b log/injar1216 -x %HOSTIP:%HTTPPORT ++ ++ ++example.fake FALSE /a FALSE 2139150993 mooo indeed ++example.fake FALSE /b FALSE 0 moo1 indeed ++example.fake FALSE /c FALSE 2139150993 moo2 indeed ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++^User-Agent:.* ++ ++ ++GET http://example.fake/c/1216 HTTP/1.1 ++Host: example.fake ++Accept: */* ++Proxy-Connection: Keep-Alive ++Cookie: moo2=indeed ++ ++GET http://bexample.fake/c/1216 HTTP/1.1 ++Host: bexample.fake ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++ ++ ++ +-- +1.7.1 + + +From 6c5a78d0407788b1092bbc8a19b68b01ccb75f8a Mon Sep 17 00:00:00 2001 +From: YAMADA Yasuharu +Date: Thu, 11 Apr 2013 00:17:15 +0200 +Subject: [PATCH 2/3] cookie: fix tailmatching to prevent cross-domain leakage + +Cookies set for 'example.com' could accidentaly also be sent by libcurl +to the 'bexample.com' (ie with a prefix to the first domain name). + +This is a security vulnerabilty, CVE-2013-1944. + +Bug: http://curl.haxx.se/docs/adv_20130412.html + +Signed-off-by: Kamil Dudka +--- + lib/cookie.c | 24 +++++++++++++++++++----- + 1 files changed, 19 insertions(+), 5 deletions(-) + +diff --git a/lib/cookie.c b/lib/cookie.c +index 18b9155..d4fd78a 100644 +--- a/lib/cookie.c ++++ b/lib/cookie.c +@@ -118,15 +118,29 @@ static void freecookie(struct Cookie *co) + free(co); + } + +-static bool tailmatch(const char *little, const char *bigone) ++static bool tailmatch(const char *cooke_domain, const char *hostname) + { +- size_t littlelen = strlen(little); +- size_t biglen = strlen(bigone); ++ size_t cookie_domain_len = strlen(cooke_domain); ++ size_t hostname_len = strlen(hostname); + +- if(littlelen > biglen) ++ if(hostname_len < cookie_domain_len) + return FALSE; + +- return Curl_raw_equal(little, bigone+biglen-littlelen) ? TRUE : FALSE; ++ if(!Curl_raw_equal(cooke_domain, hostname+hostname_len-cookie_domain_len)) ++ return FALSE; ++ ++ /* A lead char of cookie_domain is not '.'. ++ RFC6265 4.1.2.3. The Domain Attribute says: ++ For example, if the value of the Domain attribute is ++ "example.com", the user agent will include the cookie in the Cookie ++ header when making HTTP requests to example.com, www.example.com, and ++ www.corp.example.com. ++ */ ++ if(hostname_len == cookie_domain_len) ++ return TRUE; ++ if('.' == *(hostname + hostname_len - cookie_domain_len - 1)) ++ return TRUE; ++ return FALSE; + } + + /* +-- +1.7.1 + + +From 6284e78c9421911a24349621c5b63684823d12f7 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 12 Apr 2013 15:55:57 +0200 +Subject: [PATCH 3/3] test1218: another cookie tailmatch test + +These tests verify commit 3604fde3d3c9b0d, the fix for the "cookie +domain tailmatch" vulnerability. See +http://curl.haxx.se/docs/adv_20130412.html + +Conflicts: + + tests/data/Makefile.am + +Signed-off-by: Kamil Dudka +--- + tests/data/Makefile.am | 2 +- + tests/data/Makefile.in | 2 +- + tests/data/test1218 | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 63 insertions(+), 2 deletions(-) + create mode 100644 tests/data/test1218 + +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index d714e5d..3e8dae0 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 \ ++test1208 test1209 test1210 test1211 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/Makefile.in b/tests/data/Makefile.in +index a070266..71c9422 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 \ ++test1208 test1209 test1210 test1211 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/test1218 b/tests/data/test1218 +new file mode 100644 +index 0000000..7d86547 +--- /dev/null ++++ b/tests/data/test1218 +@@ -0,0 +1,61 @@ ++ ++ ++ ++HTTP ++HTTP GET ++HTTP proxy ++cookies ++ ++ ++ ++# This test is very similar to 1216, only that it sets the cookies from the ++# first site instead of reading from a file ++ ++ ++HTTP/1.1 200 OK ++Date: Tue, 25 Sep 2001 19:37:44 GMT ++Set-Cookie: domain=.example.fake; bug=fixed; ++Content-Length: 21 ++ ++This server says moo ++ ++ ++ ++# Client-side ++ ++ ++http ++ ++ ++HTTP cookies and domains with same prefix ++ ++ ++http://example.fake/c/1218 http://example.fake/c/1218 http://bexample.fake/c/1218 -b nonexisting -x %HOSTIP:%HTTPPORT ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++^User-Agent:.* ++ ++ ++GET http://example.fake/c/1218 HTTP/1.1 ++Host: example.fake ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++GET http://example.fake/c/1218 HTTP/1.1 ++Host: example.fake ++Accept: */* ++Proxy-Connection: Keep-Alive ++Cookie: bug=fixed ++ ++GET http://bexample.fake/c/1218 HTTP/1.1 ++Host: bexample.fake ++Accept: */* ++Proxy-Connection: Keep-Alive ++ ++ ++ ++ +-- +1.7.1 + diff --git a/SOURCES/0006-curl-7.29.0-25e577b3.patch b/SOURCES/0006-curl-7.29.0-25e577b3.patch new file mode 100644 index 0000000..2b6a786 --- /dev/null +++ b/SOURCES/0006-curl-7.29.0-25e577b3.patch @@ -0,0 +1,86 @@ +From 74d01a8e4d48eedc526cffaf6a6bc782b139e068 Mon Sep 17 00:00:00 2001 +From: Kim Vandry +Date: Mon, 18 Feb 2013 21:36:34 +0100 +Subject: [PATCH 1/2] Curl_resolver_is_resolved: show proper host name on failed resolve + +[upstream commit 25e577b33d00afb6630cf2cac98d6baa319e9aef] + +Signed-off-by: Kamil Dudka +--- + lib/asyn-thread.c | 35 ++++++++++++++++++++--------------- + 1 files changed, 20 insertions(+), 15 deletions(-) + +diff --git a/lib/asyn-thread.c b/lib/asyn-thread.c +index 7a8294d..c392b21 100644 +--- a/lib/asyn-thread.c ++++ b/lib/asyn-thread.c +@@ -430,8 +430,19 @@ static const char *gai_strerror(int ecode) + * error + */ + +-static void resolver_error(struct connectdata *conn, const char *host_or_proxy) ++static CURLcode resolver_error(struct connectdata *conn) + { ++ const char *host_or_proxy; ++ CURLcode rc; ++ if(conn->bits.httpproxy) { ++ host_or_proxy = "proxy"; ++ rc = CURLE_COULDNT_RESOLVE_PROXY; ++ } ++ else { ++ host_or_proxy = "host"; ++ rc = CURLE_COULDNT_RESOLVE_HOST; ++ } ++ + failf(conn->data, "Could not resolve %s: %s; %s", host_or_proxy, + conn->async.hostname, + #ifdef HAVE_GAI_STRERROR +@@ -442,6 +453,7 @@ static void resolver_error(struct connectdata *conn, const char *host_or_proxy) + Curl_strerror(conn, conn->async.status) + #endif + ); ++ return rc; + } + + /* +@@ -473,17 +485,9 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn, + if(entry) + *entry = conn->async.dns; + +- if(!conn->async.dns) { +- /* a name was not resolved */ +- if(conn->bits.httpproxy) { +- resolver_error(conn, "proxy"); +- rc = CURLE_COULDNT_RESOLVE_PROXY; +- } +- else { +- resolver_error(conn, "host"); +- rc = CURLE_COULDNT_RESOLVE_HOST; +- } +- } ++ if(!conn->async.dns) ++ /* a name was not resolved, report error */ ++ rc = resolver_error(conn); + + destroy_async_data(&conn->async); + +@@ -518,12 +522,13 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn, + + if(done) { + getaddrinfo_complete(conn); +- destroy_async_data(&conn->async); + + if(!conn->async.dns) { +- resolver_error(conn, "host"); +- return CURLE_COULDNT_RESOLVE_HOST; ++ CURLcode rc = resolver_error(conn); ++ destroy_async_data(&conn->async); ++ return rc; + } ++ destroy_async_data(&conn->async); + *entry = conn->async.dns; + } + else { +-- +1.7.1 + diff --git a/SOURCES/0007-curl-7.29.0-b37b5233.patch b/SOURCES/0007-curl-7.29.0-b37b5233.patch new file mode 100644 index 0000000..0f6a0c1 --- /dev/null +++ b/SOURCES/0007-curl-7.29.0-b37b5233.patch @@ -0,0 +1,35 @@ +From fd5664bc7322ebffb8d5532d17a743ace8a5449e Mon Sep 17 00:00:00 2001 +From: Zdenek Pavlas +Date: Fri, 26 Apr 2013 14:56:38 +0200 +Subject: [PATCH 2/2] url: initialize speed-check data for file:// protocol + +... in order to prevent an artificial timeout event based on stale +speed-check data from a previous network transfer. This commit fixes +a regression caused by 9dd85bced56f6951107f69e581c872c1e7e3e58e. + +Bug: https://bugzilla.redhat.com/906031 + +[upstream commit b37b5233cab96b5b1f2ab7f6e0b9c3df77320bba] + +Signed-off-by: Kamil Dudka +--- + lib/url.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 918ce58..b269027 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4895,6 +4895,9 @@ static CURLcode create_conn(struct SessionHandle *data, + -1, NULL); /* no upload */ + } + ++ /* since we skip do_init() */ ++ Curl_speedinit(data); ++ + return result; + } + #endif +-- +1.7.1 + diff --git a/SOURCES/0008-curl-7.29.0-192c4f78.patch b/SOURCES/0008-curl-7.29.0-192c4f78.patch new file mode 100644 index 0000000..299f386 --- /dev/null +++ b/SOURCES/0008-curl-7.29.0-192c4f78.patch @@ -0,0 +1,43 @@ +From 25089c2c69028f0549facf93f7bdbf7344277f09 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sun, 19 May 2013 23:24:29 +0200 +Subject: [PATCH] Curl_urldecode: no peeking beyond end of input buffer + +Security problem: CVE-2013-2174 + +If a program would give a string like "%FF" to curl_easy_unescape() but +ask for it to decode only the first byte, it would still parse and +decode the full hex sequence. The function then not only read beyond the +allowed buffer but it would also deduct the *unsigned* counter variable +for how many more bytes there's left to read in the buffer by two, +making the counter wrap. Continuing this, the function would go on +reading beyond the buffer and soon writing beyond the allocated target +buffer... + +Bug: http://curl.haxx.se/docs/adv_20130622.html +Reported-by: Timo Sirainen + +[upstream commit 192c4f788d48f82c03e9cef40013f34370e90737] + +Signed-off-by: Kamil Dudka +--- + lib/escape.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/lib/escape.c b/lib/escape.c +index 6a26cf8..a567edb 100644 +--- a/lib/escape.c ++++ b/lib/escape.c +@@ -159,7 +159,8 @@ CURLcode Curl_urldecode(struct SessionHandle *data, + + while(--alloc > 0) { + in = *string; +- if(('%' == in) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { ++ if(('%' == in) && (alloc > 2) && ++ ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { + /* this is two hexadecimal digits following a '%' */ + char hexstr[3]; + char *ptr; +-- +1.7.1 + diff --git a/SOURCES/0009-curl-7.29.0-3a0e931f.patch b/SOURCES/0009-curl-7.29.0-3a0e931f.patch new file mode 100644 index 0000000..0849d9d --- /dev/null +++ b/SOURCES/0009-curl-7.29.0-3a0e931f.patch @@ -0,0 +1,101 @@ +From b49d54103a4f011998195263de850642fa21f705 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Tue, 9 Jul 2013 14:59:01 +0200 +Subject: [PATCH 1/3] curl.1: document the --time-cond option in the man page + +[upstream commit 3a0e931fc715a80004958794a96b12cf90503f99] +--- + docs/curl.1 | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/docs/curl.1 b/docs/curl.1 +index 1aeeb46..4b12c3f 100644 +--- a/docs/curl.1 ++++ b/docs/curl.1 +@@ -1407,6 +1407,9 @@ default 512 bytes will be used. + If this option is used several times, the last one will be used. + + (Added in 7.20.0) ++.IP " -z, --time-cond TIME" ++Transfer based on a time condition. TIME may to be preceded by -, +, or =. ++See the corresponding sections 14.24, 14.28, and 14.29 of RFC 2068. + .IP "--tlsauthtype " + Set TLS authentication type. Currently, the only supported option is "SRP", + for TLS-SRP (RFC 5054). If \fI--tlsuser\fP and \fI--tlspassword\fP are +-- +1.7.1 + + +From fdc89d82464d90560aa5da857374906338472ed6 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Tue, 9 Jul 2013 14:59:01 +0200 +Subject: [PATCH 2/3] curl.1: document the --post303 option in the man page + +[upstream commit 39e85d99feede7cc573902e8ab6b3dd759022d9c] +--- + docs/curl.1 | 7 +++++++ + 1 files changed, 7 insertions(+), 0 deletions(-) + +diff --git a/docs/curl.1 b/docs/curl.1 +index 4b12c3f..5dd6579 100644 +--- a/docs/curl.1 ++++ b/docs/curl.1 +@@ -1038,6 +1038,13 @@ ubiquitous in web browsers, so curl does the conversion by default to maintain + consistency. However, a server may require a POST to remain a POST after such + a redirection. This option is meaningful only when using \fI-L, --location\fP + (Added in 7.19.1) ++.IP "--post303" ++(HTTP) Tells curl to respect RFC 2616/10.3.2 and not convert POST requests ++into GET requests when following a 303 redirection. The non-RFC behaviour is ++ubiquitous in web browsers, so curl does the conversion by default to maintain ++consistency. However, a server may require a POST to remain a POST after such ++a redirection. This option is meaningful only when using \fI-L, --location\fP ++(Added in 7.26.0) + .IP "--proto " + Tells curl to use the listed protocols for its initial retrieval. Protocols + are evaluated left to right, are comma separated, and are each a protocol +-- +1.7.1 + + +From 31102c7190a0a009cf0c06b23f98880cb43d4f55 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Tue, 9 Jul 2013 15:45:36 +0200 +Subject: [PATCH 3/3] Revert "curl.1: document the --time-cond option in the man page" + +This reverts commit 3a0e931fc715a80004958794a96b12cf90503f99 because +the documentation of --time-cond was duplicated by mistake. + +Reported by: Dave Reisner + +[upstream commit 45339625bc85b29225a2035a57eceda43206dd1e] +--- + docs/curl.1 | 5 +---- + 1 files changed, 1 insertions(+), 4 deletions(-) + +diff --git a/docs/curl.1 b/docs/curl.1 +index 5dd6579..b350865 100644 +--- a/docs/curl.1 ++++ b/docs/curl.1 +@@ -1414,9 +1414,6 @@ default 512 bytes will be used. + If this option is used several times, the last one will be used. + + (Added in 7.20.0) +-.IP " -z, --time-cond TIME" +-Transfer based on a time condition. TIME may to be preceded by -, +, or =. +-See the corresponding sections 14.24, 14.28, and 14.29 of RFC 2068. + .IP "--tlsauthtype " + Set TLS authentication type. Currently, the only supported option is "SRP", + for TLS-SRP (RFC 5054). If \fI--tlsuser\fP and \fI--tlspassword\fP are +@@ -1699,7 +1696,7 @@ speed-time seconds it gets aborted. speed-time is set with \fI-y\fP and is 30 + if not set. + + If this option is used several times, the last one will be used. +-.IP "-z/--time-cond |" ++.IP "-z, --time-cond |" + (HTTP/FTP) Request a file that has been modified later than the given time and + date, or one that has been modified before that time. The + can be all sorts of date strings or if it doesn't match any internal ones, it +-- +1.7.1 + diff --git a/SOURCES/0010-curl-7.29.0-7cc00d9a.patch b/SOURCES/0010-curl-7.29.0-7cc00d9a.patch new file mode 100644 index 0000000..fb44274 --- /dev/null +++ b/SOURCES/0010-curl-7.29.0-7cc00d9a.patch @@ -0,0 +1,395 @@ +From 3f411052825386a95d039435eb139a63859c3c73 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 5 Aug 2013 23:49:53 +0200 +Subject: [PATCH] FTP: when EPSV gets a 229 but fails to connect, retry with PASV + +This is a regression as this logic used to work. It isn't clear when it +broke, but I'm assuming in 7.28.0 when we went all-multi internally. + +This likely never worked with the multi interface. As the failed +connection is detected once the multi state has reached DO_MORE, the +Curl_do_more() function was now expanded somewhat so that the +ftp_do_more() function can request to go "back" to the previous state +when it makes another attempt - using PASV. + +Added test case 1233 to verify this fix. It has the little issue that it +assumes no service is listening/accepting connections on port 1... + +Reported-by: byte_bucket in the #curl IRC channel + +[upstream commit 7cc00d9a832c42a330888aa5c11a2abad1bd5ac0] + +Signed-off-by: Kamil Dudka +--- + lib/ftp.c | 64 ++++++++++++++++++++++++++++------------------- + lib/multi.c | 11 ++++++-- + lib/url.c | 10 ++++--- + lib/url.h | 4 +- + lib/urldata.h | 2 +- + tests/data/Makefile.am | 2 +- + tests/data/test1233 | 46 ++++++++++++++++++++++++++++++++++ + 7 files changed, 102 insertions(+), 37 deletions(-) + create mode 100644 tests/data/test1233 + +diff --git a/lib/ftp.c b/lib/ftp.c +index 469b887..4501116 100644 +--- a/lib/ftp.c ++++ b/lib/ftp.c +@@ -136,7 +136,7 @@ static CURLcode ftp_done(struct connectdata *conn, + CURLcode, bool premature); + static CURLcode ftp_connect(struct connectdata *conn, bool *done); + static CURLcode ftp_disconnect(struct connectdata *conn, bool dead_connection); +-static CURLcode ftp_do_more(struct connectdata *conn, bool *completed); ++static CURLcode ftp_do_more(struct connectdata *conn, int *completed); + static CURLcode ftp_multi_statemach(struct connectdata *conn, bool *done); + static int ftp_getsock(struct connectdata *conn, curl_socket_t *socks, + int numsocks); +@@ -1794,15 +1794,15 @@ static CURLcode ftp_state_quote(struct connectdata *conn, + static CURLcode ftp_epsv_disable(struct connectdata *conn) + { + CURLcode result = CURLE_OK; +- infof(conn->data, "got positive EPSV response, but can't connect. " +- "Disabling EPSV\n"); ++ infof(conn->data, "Failed EPSV attempt. Disabling EPSV\n"); + /* disable it for next transfer */ + conn->bits.ftp_use_epsv = FALSE; + conn->data->state.errorbuf = FALSE; /* allow error message to get + rewritten */ + PPSENDF(&conn->proto.ftpc.pp, "PASV", NULL); + conn->proto.ftpc.count1++; +- /* remain in the FTP_PASV state */ ++ /* remain in/go to the FTP_PASV state */ ++ state(conn, FTP_PASV); + return result; + } + +@@ -1931,15 +1931,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + } + else if(ftpc->count1 == 0) { + /* EPSV failed, move on to PASV */ +- +- /* disable it for next transfer */ +- conn->bits.ftp_use_epsv = FALSE; +- infof(data, "disabling EPSV usage\n"); +- +- PPSENDF(&ftpc->pp, "PASV", NULL); +- ftpc->count1++; +- /* remain in the FTP_PASV state */ +- return result; ++ return ftp_epsv_disable(conn); + } + else { + failf(data, "Bad PASV/EPSV response: %03d", ftpcode); +@@ -2018,14 +2010,17 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + 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: +@@ -2077,8 +2072,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn, + } + } + +- conn->bits.tcpconnect[SECONDARYSOCKET] = TRUE; +- ++ conn->bits.tcpconnect[SECONDARYSOCKET] = connected; + conn->bits.do_more = TRUE; + state(conn, FTP_STOP); /* this phase is completed */ + +@@ -3664,20 +3658,23 @@ static CURLcode ftp_range(struct connectdata *conn) + * + * This function shall be called when the second FTP (data) connection is + * connected. ++ * ++ * 'complete' can return 0 for incomplete, 1 for done and -1 for go back ++ * (which basically is only for when PASV is being sent to retry a failed ++ * EPSV). + */ + +-static CURLcode ftp_do_more(struct connectdata *conn, bool *complete) ++static CURLcode ftp_do_more(struct connectdata *conn, int *completep) + { + struct SessionHandle *data=conn->data; + struct ftp_conn *ftpc = &conn->proto.ftpc; + CURLcode result = CURLE_OK; + bool connected = FALSE; ++ bool complete = FALSE; + + /* the ftp struct is inited in ftp_connect() */ + struct FTP *ftp = data->state.proto.ftp; + +- *complete = FALSE; +- + /* if the second connection isn't done yet, wait for it */ + if(!conn->bits.tcpconnect[SECONDARYSOCKET]) { + if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) { +@@ -3694,14 +3691,22 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete) + if(connected) { + DEBUGF(infof(data, "DO-MORE connected phase starts\n")); + } +- else ++ else { ++ if(result && (ftpc->count1 == 0)) { ++ *completep = -1; /* go back to DOING please */ ++ /* this is a EPSV connect failing, try PASV instead */ ++ return ftp_epsv_disable(conn); ++ } + return result; ++ } + } + + if(ftpc->state) { + /* already in a state so skip the intial commands. + They are only done to kickstart the do_more state */ +- result = ftp_multi_statemach(conn, complete); ++ result = ftp_multi_statemach(conn, &complete); ++ ++ *completep = (int)complete; + + /* if we got an error or if we don't wait for a data connection return + immediately */ +@@ -3712,7 +3717,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete) + /* if we reach the end of the FTP state machine here, *complete will be + TRUE but so is ftpc->wait_data_conn, which says we need to wait for + the data connection and therefore we're not actually complete */ +- *complete = FALSE; ++ *completep = 0; + } + + if(ftp->transfer <= FTPTRANSFER_INFO) { +@@ -3735,6 +3740,9 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete) + + if(result) + return result; ++ ++ *completep = 1; /* this state is now complete when the server has ++ connected back to us */ + } + } + else if(data->set.upload) { +@@ -3742,7 +3750,8 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete) + if(result) + return result; + +- result = ftp_multi_statemach(conn, complete); ++ result = ftp_multi_statemach(conn, &complete); ++ *completep = (int)complete; + } + else { + /* download */ +@@ -3770,7 +3779,8 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete) + return result; + } + +- result = ftp_multi_statemach(conn, complete); ++ result = ftp_multi_statemach(conn, &complete); ++ *completep = (int)complete; + } + return result; + } +@@ -3782,7 +3792,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, bool *complete) + + if(!ftpc->wait_data_conn) { + /* no waiting for the data connection so this is now complete */ +- *complete = TRUE; ++ *completep = 1; + DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result)); + } + +@@ -3825,7 +3835,9 @@ CURLcode ftp_perform(struct connectdata *conn, + /* run the state-machine */ + result = ftp_multi_statemach(conn, dophase_done); + +- *connected = conn->bits.tcpconnect[FIRSTSOCKET]; ++ *connected = conn->bits.tcpconnect[SECONDARYSOCKET]; ++ ++ infof(conn->data, "ftp_perform ends with SECONDARY: %d\n", *connected); + + if(*dophase_done) + DEBUGF(infof(conn->data, "DO phase is complete1\n")); +@@ -4445,7 +4457,7 @@ static CURLcode ftp_dophase_done(struct connectdata *conn, + struct ftp_conn *ftpc = &conn->proto.ftpc; + + if(connected) { +- bool completed; ++ int completed; + CURLcode result = ftp_do_more(conn, &completed); + + if(result) { +diff --git a/lib/multi.c b/lib/multi.c +index 706df23..9a8e68e 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -906,6 +906,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, + struct SingleRequest *k; + struct SessionHandle *data; + long timeout_ms; ++ int control; + + if(!GOOD_EASY_HANDLE(easy->easy_handle)) + return CURLM_BAD_EASY_HANDLE; +@@ -1323,13 +1324,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, + /* + * When we are connected, DO MORE and then go DO_DONE + */ +- easy->result = Curl_do_more(easy->easy_conn, &dophase_done); ++ easy->result = Curl_do_more(easy->easy_conn, &control); + + /* No need to remove this handle from the send pipeline here since that + is done in Curl_done() */ + if(CURLE_OK == easy->result) { +- if(dophase_done) { +- multistate(easy, CURLM_STATE_DO_DONE); ++ if(control) { ++ /* if positive, advance to DO_DONE ++ if negative, go back to DOING */ ++ multistate(easy, control==1? ++ CURLM_STATE_DO_DONE: ++ CURLM_STATE_DOING); + result = CURLM_CALL_MULTI_PERFORM; + } + else +diff --git a/lib/url.c b/lib/url.c +index b269027..52f7e27 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -5394,18 +5394,20 @@ CURLcode Curl_do(struct connectdata **connp, bool *done) + * + * TODO: A future libcurl should be able to work away this state. + * ++ * 'complete' can return 0 for incomplete, 1 for done and -1 for go back to ++ * DOING state there's more work to do! + */ + +-CURLcode Curl_do_more(struct connectdata *conn, bool *completed) ++CURLcode Curl_do_more(struct connectdata *conn, int *complete) + { + CURLcode result=CURLE_OK; + +- *completed = FALSE; ++ *complete = 0; + + if(conn->handler->do_more) +- result = conn->handler->do_more(conn, completed); ++ result = conn->handler->do_more(conn, complete); + +- if(!result && *completed) ++ if(!result && (*complete == 1)) + /* do_complete must be called after the protocol-specific DO function */ + do_complete(conn); + +diff --git a/lib/url.h b/lib/url.h +index a026e90..c0d9c38 100644 +--- a/lib/url.h ++++ b/lib/url.h +@@ -7,7 +7,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 +@@ -37,7 +37,7 @@ CURLcode Curl_close(struct SessionHandle *data); /* opposite of curl_open() */ + CURLcode Curl_connect(struct SessionHandle *, struct connectdata **, + bool *async, bool *protocol_connect); + CURLcode Curl_do(struct connectdata **, bool *done); +-CURLcode Curl_do_more(struct connectdata *, bool *completed); ++CURLcode Curl_do_more(struct connectdata *, int *completed); + CURLcode Curl_done(struct connectdata **, CURLcode, bool premature); + CURLcode Curl_disconnect(struct connectdata *, bool dead_connection); + CURLcode Curl_protocol_connect(struct connectdata *conn, bool *done); +diff --git a/lib/urldata.h b/lib/urldata.h +index 7a275da..2be467b 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -550,7 +550,7 @@ struct Curl_async { + /* These function pointer types are here only to allow easier typecasting + within the source when we need to cast between data pointers (such as NULL) + and function pointers. */ +-typedef CURLcode (*Curl_do_more_func)(struct connectdata *, bool *); ++typedef CURLcode (*Curl_do_more_func)(struct connectdata *, int *); + typedef CURLcode (*Curl_done_func)(struct connectdata *, CURLcode, bool); + + +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 3e8dae0..3f6a047 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 test1216 test1218 \ +-test1220 test1221 test1222 test1223 \ ++test1220 test1221 test1222 test1223 test1233 \ + 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/test1233 b/tests/data/test1233 +new file mode 100644 +index 0000000..caf0527 +--- /dev/null ++++ b/tests/data/test1233 +@@ -0,0 +1,46 @@ ++ ++ ++ ++FTP ++ ++ ++ ++# Server-side ++ ++ ++# Assuming there's nothing listening on port 1 ++REPLY EPSV 229 Entering Passiv Mode (|||1|) ++ ++ ++here are some bytes ++ ++ ++ ++# Client-side ++ ++ ++ftp ++ ++ ++FTP failing to connect to EPSV port, switching to PASV ++ ++ ++ftp://%HOSTIP:%FTPPORT/1233 ++ ++ ++ ++# Verify data after the test has been "shot" ++ ++ ++USER anonymous ++PASS ftp@example.com ++PWD ++EPSV ++PASV ++TYPE I ++SIZE 1233 ++RETR 1233 ++QUIT ++ ++ ++ +-- +1.7.1 + diff --git a/SOURCES/0011-curl-7.29.0-0feeab78.patch b/SOURCES/0011-curl-7.29.0-0feeab78.patch new file mode 100644 index 0000000..bd6b8b3 --- /dev/null +++ b/SOURCES/0011-curl-7.29.0-0feeab78.patch @@ -0,0 +1,74 @@ +From d3036f34cce421990e8268ee4bbfc0d9f5ceb054 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 13 Jun 2013 19:27:12 +0200 +Subject: [PATCH] curl_easy_perform: avoid busy-looping + +When curl_multi_wait() finds no file descriptor to wait for, it returns +instantly and this must be handled gracefully within curl_easy_perform() +or cause a busy-loop. Starting now, repeated fast returns without any +file descriptors is detected and a gradually increasing sleep will be +used (up to a max of 1000 milliseconds) before continuing the loop. + +Bug: http://curl.haxx.se/bug/view.cgi?id=1238 +Reported-by: Miguel Angel + +[upstream commit 0feeab7802dd2a6465d22d153d8d36b2cca99b96] + +Signed-off-by: Kamil Dudka +--- + lib/easy.c | 25 +++++++++++++++++++++++++ + 1 files changed, 25 insertions(+), 0 deletions(-) + +diff --git a/lib/easy.c b/lib/easy.c +index 2739598..a7051dd 100644 +--- a/lib/easy.c ++++ b/lib/easy.c +@@ -410,6 +410,9 @@ CURLcode curl_easy_perform(CURL *easy) + bool done = FALSE; + int rc; + struct SessionHandle *data = easy; ++ int without_fds = 0; /* count number of consecutive returns from ++ curl_multi_wait() without any filedescriptors */ ++ struct timeval before; + + if(!easy) + return CURLE_BAD_FUNCTION_ARGUMENT; +@@ -445,6 +448,7 @@ CURLcode curl_easy_perform(CURL *easy) + int still_running; + int ret; + ++ before = curlx_tvnow(); + mcode = curl_multi_wait(multi, NULL, 0, 1000, &ret); + + if(mcode == CURLM_OK) { +@@ -453,6 +457,27 @@ CURLcode curl_easy_perform(CURL *easy) + code = CURLE_RECV_ERROR; + break; + } ++ else if(ret == 0) { ++ struct timeval after = curlx_tvnow(); ++ /* If it returns without any filedescriptor instantly, we need to ++ avoid busy-looping during periods where it has nothing particular ++ to wait for */ ++ 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; ++ Curl_wait_ms(sleep_ms); ++ } ++ } ++ else ++ /* it wasn't "instant", restart counter */ ++ without_fds = 0; ++ } ++ else ++ /* got file descriptor, restart counter */ ++ without_fds = 0; + + mcode = curl_multi_perform(multi, &still_running); + } +-- +1.7.1 + diff --git a/SOURCES/0012-curl-7.29.0-c639d725.patch b/SOURCES/0012-curl-7.29.0-c639d725.patch new file mode 100644 index 0000000..16d1eac --- /dev/null +++ b/SOURCES/0012-curl-7.29.0-c639d725.patch @@ -0,0 +1,519 @@ +From 9b675516d5fb09a455d1f7b7aa98e253361bedf3 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 8 Feb 2013 13:48:56 +0100 +Subject: [PATCH 1/2] DONE: consider callback-aborted transfers premature + +This bug report properly identified that when doing SMTP and aborting +the transfer with a callback, it must be considered aborted prematurely +by the code to avoid QUIT etc to be attempted as that would cause a +hang. + +The new test case 1507 verifies this behavior. + +Reported by: Patricia Muscalu +Bug: http://curl.haxx.se/bug/view.cgi?id=1184 + +[upstream commit 72688317adcedb9508fd2189e6c6d3945e06a004] + +Signed-off-by: Kamil Dudka +--- + lib/url.c | 7 ++ + tests/data/Makefile.am | 3 +- + tests/data/Makefile.in | 3 +- + tests/data/test1507 | 51 +++++++++++++ + tests/libtest/Makefile.in | 82 +++++++++++++++++++++- + tests/libtest/Makefile.inc | 6 ++- + tests/libtest/lib1507.c | 167 ++++++++++++++++++++++++++++++++++++++++++++ + 7 files changed, 313 insertions(+), 6 deletions(-) + create mode 100644 tests/data/test1507 + create mode 100644 tests/libtest/lib1507.c + +diff --git a/lib/url.c b/lib/url.c +index 52f7e27..a6375a2 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -5222,6 +5222,13 @@ CURLcode Curl_done(struct connectdata **connp, + conn->dns_entry = NULL; + } + ++ if(status == CURLE_ABORTED_BY_CALLBACK) ++ /* When we're aborted due to a callback return code it basically have to ++ be counted as premature as there is trouble ahead if we don't. We have ++ many callbacks and protocols work differently, we could potentially do ++ this more fine-grained in the future. */ ++ premature = TRUE; ++ + /* this calls the protocol-specific function pointer previously set */ + if(conn->handler->done) + result = conn->handler->done(conn, status, premature); +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index 3f6a047..805955c 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -93,7 +93,8 @@ 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 \ +-test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1508 \ ++test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ ++test1508 \ + 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 71c9422..1e6d679 100644 +--- a/tests/data/Makefile.in ++++ b/tests/data/Makefile.in +@@ -357,7 +357,8 @@ 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 \ +-test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1508 \ ++test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ ++test1508 \ + 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/test1507 b/tests/data/test1507 +new file mode 100644 +index 0000000..b66e71d +--- /dev/null ++++ b/tests/data/test1507 +@@ -0,0 +1,51 @@ ++ ++ ++ ++SMTP ++multi ++ ++ ++ ++# ++# Server-side ++ ++ ++ ++# ++# Client-side ++ ++ ++smtp ++ ++ ++lib1507 ++ ++ ++# based on bug report #1184 ++ ++SMTP with multi interface and CURLE_ABORTED_BY_CALLBACK ++ ++ ++From: different ++To: another ++ ++body ++ ++ ++smtp://%HOSTIP:%SMTPPORT/user ++ ++ ++ ++# ++# Verify data after the test has been "shot" ++ ++ ++EHLO user ++MAIL FROM:<1507-realuser@example.com> ++RCPT TO:<1507-recipient@example.com> ++DATA ++ ++ ++ ++ ++ +diff --git a/tests/libtest/Makefile.in b/tests/libtest/Makefile.in +index 7683c09..e6826c0 100644 +--- a/tests/libtest/Makefile.in ++++ b/tests/libtest/Makefile.in +@@ -85,7 +85,8 @@ noinst_PROGRAMS = chkhostname$(EXEEXT) libauthretry$(EXEEXT) \ + lib591$(EXEEXT) lib597$(EXEEXT) lib598$(EXEEXT) \ + lib599$(EXEEXT) lib1500$(EXEEXT) lib1501$(EXEEXT) \ + lib1502$(EXEEXT) lib1503$(EXEEXT) lib1504$(EXEEXT) \ +- lib1505$(EXEEXT) lib1506$(EXEEXT) lib1508$(EXEEXT) ++ lib1505$(EXEEXT) lib1506$(EXEEXT) lib1507$(EXEEXT) \ ++ lib1508$(EXEEXT) + subdir = tests/libtest + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 + am__aclocal_m4_deps = $(top_srcdir)/m4/curl-compilers.m4 \ +@@ -173,6 +174,13 @@ am_lib1506_OBJECTS = lib1506-lib1506.$(OBJEXT) $(am__objects_18) \ + $(am__objects_19) $(am__objects_20) + lib1506_OBJECTS = $(am_lib1506_OBJECTS) + lib1506_DEPENDENCIES = $(am__DEPENDENCIES_1) ++am__objects_154 = lib1507-first.$(OBJEXT) ++am__objects_155 = lib1507-testutil.$(OBJEXT) ++am__objects_156 = lib1507-warnless.$(OBJEXT) ++am_lib1507_OBJECTS = lib1507-lib1507.$(OBJEXT) $(am__objects_154) \ ++ $(am__objects_155) $(am__objects_156) ++lib1507_OBJECTS = $(am_lib1507_OBJECTS) ++lib1507_DEPENDENCIES = $(am__DEPENDENCIES_1) + am__objects_151 = lib1508-first.$(OBJEXT) + am__objects_152 = lib1508-testutil.$(OBJEXT) + am__objects_153 = lib1508-warnless.$(OBJEXT) +@@ -639,7 +647,8 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + SOURCES = $(libhostname_la_SOURCES) $(chkhostname_SOURCES) \ + $(lib1500_SOURCES) $(lib1501_SOURCES) $(lib1502_SOURCES) \ + $(lib1503_SOURCES) $(lib1504_SOURCES) $(lib1505_SOURCES) \ +- $(lib1506_SOURCES) $(lib1508_SOURCES) $(lib500_SOURCES) $(lib501_SOURCES) \ ++ $(lib1506_SOURCES) $(lib1507_SOURCES) $(lib1508_SOURCES) \ ++ $(lib500_SOURCES) $(lib501_SOURCES) \ + $(lib502_SOURCES) $(lib503_SOURCES) $(lib504_SOURCES) \ + $(lib505_SOURCES) $(lib506_SOURCES) $(lib507_SOURCES) \ + $(lib508_SOURCES) $(lib510_SOURCES) $(lib511_SOURCES) \ +@@ -669,7 +678,8 @@ SOURCES = $(libhostname_la_SOURCES) $(chkhostname_SOURCES) \ + DIST_SOURCES = $(libhostname_la_SOURCES) $(chkhostname_SOURCES) \ + $(lib1500_SOURCES) $(lib1501_SOURCES) $(lib1502_SOURCES) \ + $(lib1503_SOURCES) $(lib1504_SOURCES) $(lib1505_SOURCES) \ +- $(lib1506_SOURCES) $(lib1508_SOURCES) $(lib500_SOURCES) $(lib501_SOURCES) \ ++ $(lib1506_SOURCES) $(lib1507_SOURCES) $(lib1508_SOURCES) \ ++ $(lib500_SOURCES) $(lib501_SOURCES) \ + $(lib502_SOURCES) $(lib503_SOURCES) $(lib504_SOURCES) \ + $(lib505_SOURCES) $(lib506_SOURCES) $(lib507_SOURCES) \ + $(lib508_SOURCES) $(lib510_SOURCES) $(lib511_SOURCES) \ +@@ -1162,6 +1172,9 @@ lib1505_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1505 + lib1506_SOURCES = lib1506.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) + lib1506_LDADD = $(TESTUTIL_LIBS) + lib1506_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1506 ++lib1507_SOURCES = lib1507.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) ++lib1507_LDADD = $(TESTUTIL_LIBS) ++lib1507_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1507 + lib1508_SOURCES = lib1508.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) + lib1508_LDADD = $(TESTUTIL_LIBS) + lib1508_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1508 +@@ -1263,6 +1276,9 @@ lib1505$(EXEEXT): $(lib1505_OBJECTS) $(lib1505_DEPENDENCIES) $(EXTRA_lib1505_DEP + lib1506$(EXEEXT): $(lib1506_OBJECTS) $(lib1506_DEPENDENCIES) $(EXTRA_lib1506_DEPENDENCIES) + @rm -f lib1506$(EXEEXT) + $(LINK) $(lib1506_OBJECTS) $(lib1506_LDADD) $(LIBS) ++lib1507$(EXEEXT): $(lib1507_OBJECTS) $(lib1507_DEPENDENCIES) $(EXTRA_lib1507_DEPENDENCIES) ++ @rm -f lib1507$(EXEEXT) ++ $(LINK) $(lib1507_OBJECTS) $(lib1507_LDADD) $(LIBS) + lib1508$(EXEEXT): $(lib1508_OBJECTS) $(lib1508_DEPENDENCIES) $(EXTRA_lib1508_DEPENDENCIES) + @rm -f lib1508$(EXEEXT) + $(LINK) $(lib1508_OBJECTS) $(lib1508_LDADD) $(LIBS) +@@ -1533,6 +1549,10 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1506-lib1506.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1506-testutil.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1506-warnless.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1507-first.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1507-lib1507.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1507-testutil.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1507-warnless.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1508-first.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1508-lib1508.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib1508-testutil.Po@am__quote@ +@@ -2180,6 +2200,62 @@ lib1506-warnless.obj: ../../lib/warnless.c + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1506_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1506-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi` + ++lib1507-lib1507.o: lib1507.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1507-lib1507.o -MD -MP -MF $(DEPDIR)/lib1507-lib1507.Tpo -c -o lib1507-lib1507.o `test -f 'lib1507.c' || echo '$(srcdir)/'`lib1507.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1507-lib1507.Tpo $(DEPDIR)/lib1507-lib1507.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lib1507.c' object='lib1507-lib1507.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1507-lib1507.o `test -f 'lib1507.c' || echo '$(srcdir)/'`lib1507.c ++ ++lib1507-lib1507.obj: lib1507.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1507-lib1507.obj -MD -MP -MF $(DEPDIR)/lib1507-lib1507.Tpo -c -o lib1507-lib1507.obj `if test -f 'lib1507.c'; then $(CYGPATH_W) 'lib1507.c'; else $(CYGPATH_W) '$(srcdir)/lib1507.c'; fi` ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1507-lib1507.Tpo $(DEPDIR)/lib1507-lib1507.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='lib1507.c' object='lib1507-lib1507.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1507-lib1507.obj `if test -f 'lib1507.c'; then $(CYGPATH_W) 'lib1507.c'; else $(CYGPATH_W) '$(srcdir)/lib1507.c'; fi` ++ ++lib1507-first.o: first.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1507-first.o -MD -MP -MF $(DEPDIR)/lib1507-first.Tpo -c -o lib1507-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1507-first.Tpo $(DEPDIR)/lib1507-first.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='first.c' object='lib1507-first.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1507-first.o `test -f 'first.c' || echo '$(srcdir)/'`first.c ++ ++lib1507-first.obj: first.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1507-first.obj -MD -MP -MF $(DEPDIR)/lib1507-first.Tpo -c -o lib1507-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi` ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1507-first.Tpo $(DEPDIR)/lib1507-first.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='first.c' object='lib1507-first.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1507-first.obj `if test -f 'first.c'; then $(CYGPATH_W) 'first.c'; else $(CYGPATH_W) '$(srcdir)/first.c'; fi` ++ ++lib1507-testutil.o: testutil.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1507-testutil.o -MD -MP -MF $(DEPDIR)/lib1507-testutil.Tpo -c -o lib1507-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1507-testutil.Tpo $(DEPDIR)/lib1507-testutil.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='testutil.c' object='lib1507-testutil.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1507-testutil.o `test -f 'testutil.c' || echo '$(srcdir)/'`testutil.c ++ ++lib1507-testutil.obj: testutil.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1507-testutil.obj -MD -MP -MF $(DEPDIR)/lib1507-testutil.Tpo -c -o lib1507-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi` ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1507-testutil.Tpo $(DEPDIR)/lib1507-testutil.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='testutil.c' object='lib1507-testutil.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1507-testutil.obj `if test -f 'testutil.c'; then $(CYGPATH_W) 'testutil.c'; else $(CYGPATH_W) '$(srcdir)/testutil.c'; fi` ++ ++lib1507-warnless.o: ../../lib/warnless.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1507-warnless.o -MD -MP -MF $(DEPDIR)/lib1507-warnless.Tpo -c -o lib1507-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1507-warnless.Tpo $(DEPDIR)/lib1507-warnless.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../lib/warnless.c' object='lib1507-warnless.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1507-warnless.o `test -f '../../lib/warnless.c' || echo '$(srcdir)/'`../../lib/warnless.c ++ ++lib1507-warnless.obj: ../../lib/warnless.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1507-warnless.obj -MD -MP -MF $(DEPDIR)/lib1507-warnless.Tpo -c -o lib1507-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__mv) $(DEPDIR)/lib1507-warnless.Tpo $(DEPDIR)/lib1507-warnless.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='../../lib/warnless.c' object='lib1507-warnless.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1507_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib1507-warnless.obj `if test -f '../../lib/warnless.c'; then $(CYGPATH_W) '../../lib/warnless.c'; else $(CYGPATH_W) '$(srcdir)/../../lib/warnless.c'; fi` ++ + lib1508-lib1508.o: lib1508.c + @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib1508_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib1508-lib1508.o -MD -MP -MF $(DEPDIR)/lib1508-lib1508.Tpo -c -o lib1508-lib1508.o `test -f 'lib1508.c' || echo '$(srcdir)/'`lib1508.c + @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/lib1508-lib1508.Tpo $(DEPDIR)/lib1508-lib1508.Po +diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc +index 8bf2be4..5e377d3 100644 +--- a/tests/libtest/Makefile.inc ++++ b/tests/libtest/Makefile.inc +@@ -23,7 +23,7 @@ noinst_PROGRAMS = chkhostname libauthretry libntlmconnect \ + lib582 lib583 lib585 lib586 lib587 \ + lib590 lib591 lib597 lib598 lib599 \ + \ +- lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1508 ++ lib1500 lib1501 lib1502 lib1503 lib1504 lib1505 lib1506 lib1507 lib1508 + + chkhostname_SOURCES = chkhostname.c ../../lib/curl_gethostname.c + chkhostname_LDADD = @CURL_NETWORK_LIBS@ +@@ -313,6 +313,10 @@ lib1506_SOURCES = lib1506.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) + lib1506_LDADD = $(TESTUTIL_LIBS) + lib1506_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1506 + ++lib1507_SOURCES = lib1507.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) ++lib1507_LDADD = $(TESTUTIL_LIBS) ++lib1507_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1507 ++ + lib1508_SOURCES = lib1508.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS) + lib1508_LDADD = $(TESTUTIL_LIBS) + lib1508_CPPFLAGS = $(AM_CPPFLAGS) -DLIB1508 +diff --git a/tests/libtest/lib1507.c b/tests/libtest/lib1507.c +new file mode 100644 +index 0000000..7c4e6ed +--- /dev/null ++++ b/tests/libtest/lib1507.c +@@ -0,0 +1,167 @@ ++/*************************************************************************** ++ * _ _ ____ _ ++ * 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 "test.h" ++ ++#include "testutil.h" ++#include "warnless.h" ++#include "memdebug.h" ++ ++/* ++ * This is the list of basic details you need to tweak to get things right. ++ */ ++#define USERNAME "user@example.com" ++#define PASSWORD "123qwerty" ++#define RECIPIENT "<1507-recipient@example.com>" ++#define MAILFROM "<1507-realuser@example.com>" ++ ++#define MULTI_PERFORM_HANG_TIMEOUT 60 * 1000 ++ ++static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp) ++{ ++ (void)ptr; ++ (void)size; ++ (void)nmemb; ++ (void)userp; ++ return CURL_READFUNC_ABORT; ++} ++ ++static struct timeval tvnow(void) ++{ ++ /* ++ ** time() returns the value of time in seconds since the Epoch. ++ */ ++ struct timeval now; ++ now.tv_sec = (long)time(NULL); ++ now.tv_usec = 0; ++ return now; ++} ++ ++static long tvdiff(struct timeval newer, struct timeval older) ++{ ++ return (newer.tv_sec-older.tv_sec)*1000+ ++ (newer.tv_usec-older.tv_usec)/1000; ++} ++ ++int test(char *URL) ++{ ++ CURL *curl; ++ CURLM *mcurl; ++ int still_running = 1; ++ struct timeval mp_start; ++ struct curl_slist* rcpt_list = NULL; ++ ++ curl_global_init(CURL_GLOBAL_DEFAULT); ++ ++ curl = curl_easy_init(); ++ if(!curl) ++ return 1; ++ ++ mcurl = curl_multi_init(); ++ if(!mcurl) ++ return 2; ++ ++ rcpt_list = curl_slist_append(rcpt_list, RECIPIENT); ++ /* more addresses can be added here ++ rcpt_list = curl_slist_append(rcpt_list, ""); ++ */ ++ ++ curl_easy_setopt(curl, CURLOPT_URL, URL); ++#if 0 ++ curl_easy_setopt(curl, CURLOPT_USERNAME, USERNAME); ++ curl_easy_setopt(curl, CURLOPT_PASSWORD, PASSWORD); ++#endif ++ curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); ++ curl_easy_setopt(curl, CURLOPT_MAIL_FROM, MAILFROM); ++ curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, rcpt_list); ++ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); ++ curl_multi_add_handle(mcurl, curl); ++ ++ mp_start = tvnow(); ++ ++ /* we start some action by calling perform right away */ ++ curl_multi_perform(mcurl, &still_running); ++ ++ while(still_running) { ++ struct timeval timeout; ++ int rc; /* select() return code */ ++ ++ fd_set fdread; ++ fd_set fdwrite; ++ fd_set fdexcep; ++ int maxfd = -1; ++ ++ long curl_timeo = -1; ++ ++ FD_ZERO(&fdread); ++ FD_ZERO(&fdwrite); ++ FD_ZERO(&fdexcep); ++ ++ /* set a suitable timeout to play around with */ ++ timeout.tv_sec = 1; ++ timeout.tv_usec = 0; ++ ++ curl_multi_timeout(mcurl, &curl_timeo); ++ if(curl_timeo >= 0) { ++ timeout.tv_sec = curl_timeo / 1000; ++ if(timeout.tv_sec > 1) ++ timeout.tv_sec = 1; ++ else ++ timeout.tv_usec = (curl_timeo % 1000) * 1000; ++ } ++ ++ /* get file descriptors from the transfers */ ++ curl_multi_fdset(mcurl, &fdread, &fdwrite, &fdexcep, &maxfd); ++ ++ /* In a real-world program you OF COURSE check the return code of the ++ function calls. On success, the value of maxfd is guaranteed to be ++ greater or equal than -1. We call select(maxfd + 1, ...), specially in ++ case of (maxfd == -1), we call select(0, ...), which is basically equal ++ to sleep. */ ++ ++ rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout); ++ ++ if (tvdiff(tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) { ++ fprintf(stderr, "ABORTING TEST, since it seems " ++ "that it would have run forever.\n"); ++ break; ++ } ++ ++ switch(rc) { ++ case -1: ++ /* select error */ ++ break; ++ case 0: /* timeout */ ++ default: /* action */ ++ curl_multi_perform(mcurl, &still_running); ++ break; ++ } ++ } ++ ++ curl_slist_free_all(rcpt_list); ++ curl_multi_remove_handle(mcurl, curl); ++ curl_multi_cleanup(mcurl); ++ curl_easy_cleanup(curl); ++ curl_global_cleanup(); ++ return 0; ++} ++ ++ +-- +1.7.1 + + +From 55004df420d1e520d84fded41a4d16f36acee119 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 9 Sep 2013 13:10:53 +0200 +Subject: [PATCH 2/2] url: handle abortion by read/write callbacks, too + +Otherwise, the FTP protocol would unnecessarily hang 60 seconds if +aborted in the CURLOPT_HEADERFUNCTION callback. + +Reported by: Tomas Mlcoch +Bug: https://bugzilla.redhat.com/1005686 + +[upstream commit c639d725a37c91fb49bb3a689cb2596fad3a0645] +--- + lib/url.c | 8 +++++++- + 1 files changed, 7 insertions(+), 1 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index a6375a2..bddbd91 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -5222,12 +5222,18 @@ CURLcode Curl_done(struct connectdata **connp, + conn->dns_entry = NULL; + } + +- if(status == CURLE_ABORTED_BY_CALLBACK) ++ switch(status) { ++ case CURLE_ABORTED_BY_CALLBACK: ++ case CURLE_READ_ERROR: ++ case CURLE_WRITE_ERROR: + /* When we're aborted due to a callback return code it basically have to + be counted as premature as there is trouble ahead if we don't. We have + many callbacks and protocols work differently, we could potentially do + this more fine-grained in the future. */ + premature = TRUE; ++ default: ++ break; ++ } + + /* this calls the protocol-specific function pointer previously set */ + if(conn->handler->done) +-- +1.7.1 + diff --git a/SOURCES/0013-curl-7.29.0-665c160f.patch b/SOURCES/0013-curl-7.29.0-665c160f.patch new file mode 100644 index 0000000..d7c2ddf --- /dev/null +++ b/SOURCES/0013-curl-7.29.0-665c160f.patch @@ -0,0 +1,86 @@ +From 311a22b801693bf8b748169f35bde7bef744da8c Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 29 Jan 2014 12:55:36 +0100 +Subject: [PATCH 1/2] nss: do not fail if NSS does not implement a cipher + +... that the user does not ask for + +[upstream commit e15e73b741a2ddc88d166d2cec86d2bebb5d349e] +--- + lib/nss.c | 9 +++++---- + 1 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index a2c5c63..c4ffe7b 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -192,14 +192,13 @@ static SECStatus set_ciphers(struct SessionHandle *data, PRFileDesc * model, + PRBool cipher_state[NUM_OF_CIPHERS]; + PRBool found; + char *cipher; +- SECStatus rv; + + /* First disable all ciphers. This uses a different max value in case + * NSS adds more ciphers later we don't want them available by + * accident + */ + for(i=0; i +Date: Wed, 29 Jan 2014 13:03:46 +0100 +Subject: [PATCH 2/2] nss: do not use the NSS_ENABLE_ECC define + +It is not provided by NSS public headers. + +Bug: https://bugzilla.redhat.com/1058776 + +[upstream commit 665c160f0a4635565b44704ca281d2a03e715d6d] +--- + lib/nss.c | 2 -- + 1 files changed, 0 insertions(+), 2 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index c4ffe7b..111982f 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -126,7 +126,6 @@ static const cipher_s cipherlist[] = { + /* AES ciphers. */ + {"rsa_aes_128_sha", TLS_RSA_WITH_AES_128_CBC_SHA}, + {"rsa_aes_256_sha", TLS_RSA_WITH_AES_256_CBC_SHA}, +-#ifdef NSS_ENABLE_ECC + /* ECC ciphers. */ + {"ecdh_ecdsa_null_sha", TLS_ECDH_ECDSA_WITH_NULL_SHA}, + {"ecdh_ecdsa_rc4_128_sha", TLS_ECDH_ECDSA_WITH_RC4_128_SHA}, +@@ -153,7 +152,6 @@ 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}, +-#endif + }; + + /* following ciphers are new in NSS 3.4 and not enabled by default, therefore +-- +1.7.1 + diff --git a/SOURCES/0014-curl-7.29.0-8ae35102.patch b/SOURCES/0014-curl-7.29.0-8ae35102.patch new file mode 100644 index 0000000..9daa26d --- /dev/null +++ b/SOURCES/0014-curl-7.29.0-8ae35102.patch @@ -0,0 +1,42 @@ +From 8683703ef3978983e61329801aecc554aec06055 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 7 Jan 2014 09:33:54 +0100 +Subject: [PATCH] ConnectionExists: fix NTLM check for new connection + +When the requested authentication bitmask includes NTLM, we cannot +re-use a connection for another username/password as we then risk +re-using NTLM (connection-based auth). + +This has the unfortunate downside that if you include NTLM as a possible +auth, you cannot re-use connections for other usernames/passwords even +if NTLM doesn't end up the auth type used. + +Reported-by: Paras S +Patched-by: Paras S +Bug: http://curl.haxx.se/mail/lib-2014-01/0046.html + +[upstream commit 8ae35102c43d8d06572c3a1292eb6e27e663c78d] + +Signed-off-by: Kamil Dudka +--- + lib/url.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index bddbd91..313ec3e 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -2782,8 +2782,8 @@ ConnectionExists(struct SessionHandle *data, + struct connectdata *check; + struct connectdata *chosen = 0; + bool canPipeline = IsPipeliningPossible(data, needle); +- bool wantNTLM = (data->state.authhost.want==CURLAUTH_NTLM) || +- (data->state.authhost.want==CURLAUTH_NTLM_WB) ? TRUE : FALSE; ++ bool wantNTLM = (data->state.authhost.want & CURLAUTH_NTLM) || ++ (data->state.authhost.want & CURLAUTH_NTLM_WB) ? TRUE : FALSE; + struct connectbundle *bundle; + + /* Look up the bundle with all the connections to this +-- +1.7.1 + diff --git a/SOURCES/0015-curl-7.29.0-7fc9325a.patch b/SOURCES/0015-curl-7.29.0-7fc9325a.patch new file mode 100644 index 0000000..7b6c5fe --- /dev/null +++ b/SOURCES/0015-curl-7.29.0-7fc9325a.patch @@ -0,0 +1,1090 @@ +From a7b1ea3537b30450ad82d2c64d31dcecaed60fca Mon Sep 17 00:00:00 2001 +From: Gergely Nagy +Date: Thu, 19 Sep 2013 15:17:13 +0200 +Subject: [PATCH 1/9] SSL: protocol version can be specified more precisely + +CURL_SSLVERSION_TLSv1_0, CURL_SSLVERSION_TLSv1_1, +CURL_SSLVERSION_TLSv1_2 enum values are added to force exact TLS version +(CURL_SSLVERSION_TLSv1 means TLS 1.x). + +axTLS: +axTLS only supports TLS 1.0 and 1.1 but it cannot be set that only one +of these should be used, so we don't allow the new enum values. + +darwinssl: +Added support for the new enum values. + +SChannel: +Added support for the new enum values. + +CyaSSL: +Added support for the new enum values. +Bug: The original CURL_SSLVERSION_TLSv1 value enables only TLS 1.0 (it +did the same before this commit), because CyaSSL cannot be configured to +use TLS 1.0-1.2. + +GSKit: +GSKit doesn't seem to support TLS 1.1 and TLS 1.2, so we do not allow +those values. +Bugfix: There was a typo that caused wrong SSL versions to be passed to +GSKit. + +NSS: +TLS minor version cannot be set, so we don't allow the new enum values. + +QsoSSL: +TLS minor version cannot be set, so we don't allow the new enum values. + +OpenSSL: +Added support for the new enum values. +Bugfix: The original CURL_SSLVERSION_TLSv1 value enabled only TLS 1.0, +now it enables 1.0-1.2. + +Command-line tool: +Added command line options for the new values. + +[upstream commit ad34a2d5c87c7f4b14e8dded34569395de0d8c5b] +--- + docs/libcurl/curl_easy_setopt.3 | 8 +++++- + docs/libcurl/symbols-in-versions | 3 ++ + include/curl/curl.h | 5 +++- + lib/axtls.c | 3 +- + lib/curl_darwinssl.c | 34 +++++++++++++++++++++++++ + lib/curl_schannel.c | 9 ++++++ + lib/cyassl.c | 13 +++++++++- + lib/nss.c | 6 ++++ + lib/qssl.c | 6 ++++ + lib/ssluse.c | 51 +++++++++++++++++++++++++++---------- + packages/OS400/curl.inc.in | 6 ++++ + src/tool_getparam.c | 25 ++++++++++++++++-- + src/tool_setopt.c | 3 ++ + 13 files changed, 151 insertions(+), 21 deletions(-) + +diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 +index 3d31aef..92db8f4 100644 +--- a/docs/libcurl/curl_easy_setopt.3 ++++ b/docs/libcurl/curl_easy_setopt.3 +@@ -2219,11 +2219,17 @@ The default action. This will attempt to figure out the remote SSL protocol + version, i.e. either SSLv3 or TLSv1 (but not SSLv2, which became disabled + by default with 7.18.1). + .IP CURL_SSLVERSION_TLSv1 +-Force TLSv1 ++Force TLSv1.x + .IP CURL_SSLVERSION_SSLv2 + Force SSLv2 + .IP CURL_SSLVERSION_SSLv3 + Force SSLv3 ++.IP CURL_SSLVERSION_TLSv1_0 ++Force TLSv1.0 ++.IP CURL_SSLVERSION_TLSv1_1 ++Force TLSv1.1 ++.IP CURL_SSLVERSION_TLSv1_2 ++Force TLSv1.2 + .RE + .IP CURLOPT_SSL_VERIFYPEER + Pass a long as parameter. By default, curl assumes a value of 1. +diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions +index 37b5e27..57fa6eb 100644 +--- a/docs/libcurl/symbols-in-versions ++++ b/docs/libcurl/symbols-in-versions +@@ -678,6 +678,9 @@ CURL_SSLVERSION_DEFAULT 7.9.2 + CURL_SSLVERSION_SSLv2 7.9.2 + CURL_SSLVERSION_SSLv3 7.9.2 + CURL_SSLVERSION_TLSv1 7.9.2 ++CURL_SSLVERSION_TLSv1_0 7.33.0 ++CURL_SSLVERSION_TLSv1_1 7.33.0 ++CURL_SSLVERSION_TLSv1_2 7.33.0 + CURL_TIMECOND_IFMODSINCE 7.9.7 + CURL_TIMECOND_IFUNMODSINCE 7.9.7 + CURL_TIMECOND_LASTMOD 7.9.7 +diff --git a/include/curl/curl.h b/include/curl/curl.h +index 80e4cf5..8e548e3 100644 +--- a/include/curl/curl.h ++++ b/include/curl/curl.h +@@ -1625,9 +1625,12 @@ enum CURL_NETRC_OPTION { + + enum { + CURL_SSLVERSION_DEFAULT, +- CURL_SSLVERSION_TLSv1, ++ CURL_SSLVERSION_TLSv1, /* TLS 1.x */ + CURL_SSLVERSION_SSLv2, + CURL_SSLVERSION_SSLv3, ++ CURL_SSLVERSION_TLSv1_0, ++ CURL_SSLVERSION_TLSv1_1, ++ CURL_SSLVERSION_TLSv1_2, + + CURL_SSLVERSION_LAST /* never use, keep last */ + }; +diff --git a/lib/axtls.c b/lib/axtls.c +index d512950..68794b5 100644 +--- a/lib/axtls.c ++++ b/lib/axtls.c +@@ -169,7 +169,8 @@ Curl_axtls_connect(struct connectdata *conn, + case CURL_SSLVERSION_TLSv1: + break; + default: +- failf(data, "axTLS only supports TLSv1"); ++ failf(data, "axTLS only supports TLS 1.0 and 1.1, " ++ "and it cannot be specified which one to use"); + return CURLE_SSL_CONNECT_ERROR; + } + +diff --git a/lib/curl_darwinssl.c b/lib/curl_darwinssl.c +index 827c876..69eff8a 100644 +--- a/lib/curl_darwinssl.c ++++ b/lib/curl_darwinssl.c +@@ -719,6 +719,18 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); + break; ++ case CURL_SSLVERSION_TLSv1_0: ++ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol1); ++ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol1); ++ break; ++ case CURL_SSLVERSION_TLSv1_1: ++ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol11); ++ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol11); ++ break; ++ case CURL_SSLVERSION_TLSv1_2: ++ (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kTLSProtocol12); ++ (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kTLSProtocol12); ++ break; + case CURL_SSLVERSION_SSLv3: + (void)SSLSetProtocolVersionMin(connssl->ssl_ctx, kSSLProtocol3); + (void)SSLSetProtocolVersionMax(connssl->ssl_ctx, kSSLProtocol3); +@@ -759,6 +771,21 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, + kTLSProtocol12, + true); + break; ++ case CURL_SSLVERSION_TLSv1_0: ++ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, ++ kTLSProtocol1, ++ true); ++ break; ++ case CURL_SSLVERSION_TLSv1_1: ++ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, ++ kTLSProtocol11, ++ true); ++ break; ++ case CURL_SSLVERSION_TLSv1_2: ++ (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, ++ kTLSProtocol12, ++ true); ++ break; + case CURL_SSLVERSION_SSLv3: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol3, +@@ -785,10 +812,17 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn, + true); + break; + case CURL_SSLVERSION_TLSv1: ++ case CURL_SSLVERSION_TLSv1_0: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kTLSProtocol1, + true); + break; ++ case CURL_SSLVERSION_TLSv1_1: ++ failf(data, "Your version of the OS does not support TLSv1.1"); ++ return CURLE_SSL_CONNECT_ERROR; ++ case CURL_SSLVERSION_TLSv1_2: ++ failf(data, "Your version of the OS does not support TLSv1.2"); ++ return CURLE_SSL_CONNECT_ERROR; + case CURL_SSLVERSION_SSLv2: + (void)SSLSetProtocolVersionEnabled(connssl->ssl_ctx, + kSSLProtocol2, +diff --git a/lib/curl_schannel.c b/lib/curl_schannel.c +index a615f57..19b7f71 100644 +--- a/lib/curl_schannel.c ++++ b/lib/curl_schannel.c +@@ -180,6 +180,15 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) + SP_PROT_TLS1_1_CLIENT | + SP_PROT_TLS1_2_CLIENT; + break; ++ case CURL_SSLVERSION_TLSv1_0: ++ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_0_CLIENT; ++ break; ++ case CURL_SSLVERSION_TLSv1_1: ++ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_1_CLIENT; ++ break; ++ case CURL_SSLVERSION_TLSv1_2: ++ schannel_cred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT; ++ break; + case CURL_SSLVERSION_SSLv3: + schannel_cred.grbitEnabledProtocols = SP_PROT_SSL3_CLIENT; + break; +diff --git a/lib/cyassl.c b/lib/cyassl.c +index 7c78464..ff11bdd 100644 +--- a/lib/cyassl.c ++++ b/lib/cyassl.c +@@ -5,7 +5,7 @@ + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * +- * Copyright (C) 1998 - 2012, 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 +@@ -98,8 +98,19 @@ cyassl_connect_step1(struct connectdata *conn, + req_method = SSLv23_client_method(); + break; + case CURL_SSLVERSION_TLSv1: ++ infof(data, "CyaSSL cannot be configured to use TLS 1.0-1.2, " ++ "TLS 1.0 is used exclusively\n"); + req_method = TLSv1_client_method(); + break; ++ case CURL_SSLVERSION_TLSv1_0: ++ req_method = TLSv1_client_method(); ++ break; ++ case CURL_SSLVERSION_TLSv1_1: ++ req_method = TLSv1_1_client_method(); ++ break; ++ case CURL_SSLVERSION_TLSv1_2: ++ req_method = TLSv1_2_client_method(); ++ break; + case CURL_SSLVERSION_SSLv3: + req_method = SSLv3_client_method(); + break; +diff --git a/lib/nss.c b/lib/nss.c +index 111982f..ff93a38 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1266,6 +1266,12 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + case CURL_SSLVERSION_SSLv3: + ssl3 = PR_TRUE; + break; ++ case CURL_SSLVERSION_TLSv1_0: ++ case CURL_SSLVERSION_TLSv1_1: ++ case CURL_SSLVERSION_TLSv1_2: ++ failf(data, "TLS minor version cannot be set\n"); ++ curlerr = CURLE_SSL_CONNECT_ERROR; ++ goto error; + } + + if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess) +diff --git a/lib/qssl.c b/lib/qssl.c +index 8ef6fec..8b5e499 100644 +--- a/lib/qssl.c ++++ b/lib/qssl.c +@@ -206,6 +206,12 @@ static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex) + case CURL_SSLVERSION_SSLv3: + h->protocol = SSL_VERSION_3; + break; ++ ++ case CURL_SSLVERSION_TLSv1_0: ++ case CURL_SSLVERSION_TLSv1_1: ++ case CURL_SSLVERSION_TLSv1_2: ++ failf(data, "TLS minor version cannot be set"); ++ return CURLE_SSL_CONNECT_ERROR; + } + + rc = SSL_Handshake(h, SSL_HANDSHAKE_AS_CLIENT); +diff --git a/lib/ssluse.c b/lib/ssluse.c +index 4a0dba7..dd99435 100644 +--- a/lib/ssluse.c ++++ b/lib/ssluse.c +@@ -1389,19 +1389,12 @@ ossl_connect_step1(struct connectdata *conn, + switch(data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: +-#ifdef USE_TLS_SRP +- if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { +- infof(data, "Set version TLSv1 for SRP authorisation\n"); +- req_method = TLSv1_client_method() ; +- } +- else +-#endif +- /* we try to figure out version */ +- req_method = SSLv23_client_method(); +- use_sni(TRUE); +- break; + case CURL_SSLVERSION_TLSv1: +- req_method = TLSv1_client_method(); ++ case CURL_SSLVERSION_TLSv1_0: ++ case CURL_SSLVERSION_TLSv1_1: ++ case CURL_SSLVERSION_TLSv1_2: ++ /* it will be handled later with the context options */ ++ req_method = SSLv23_client_method(); + use_sni(TRUE); + break; + case CURL_SSLVERSION_SSLv2: +@@ -1514,9 +1507,39 @@ ossl_connect_step1(struct connectdata *conn, + ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + #endif + +- /* disable SSLv2 in the default case (i.e. allow SSLv3 and TLSv1) */ +- if(data->set.ssl.version == CURL_SSLVERSION_DEFAULT) ++ switch(data->set.ssl.version) { ++ case CURL_SSLVERSION_DEFAULT: ++ ctx_options |= SSL_OP_NO_SSLv2; ++#ifdef USE_TLS_SRP ++ if(data->set.ssl.authtype == CURL_TLSAUTH_SRP) { ++ infof(data, "Set version TLSv1.x for SRP authorisation\n"); ++ ctx_options |= SSL_OP_NO_SSLv3; ++ } ++#endif ++ break; ++ case CURL_SSLVERSION_TLSv1: ++ ctx_options |= SSL_OP_NO_SSLv2; ++ ctx_options |= SSL_OP_NO_SSLv3; ++ break; ++ case CURL_SSLVERSION_TLSv1_0: + ctx_options |= SSL_OP_NO_SSLv2; ++ ctx_options |= SSL_OP_NO_SSLv3; ++ ctx_options |= SSL_OP_NO_TLSv1_1; ++ ctx_options |= SSL_OP_NO_TLSv1_2; ++ break; ++ case CURL_SSLVERSION_TLSv1_1: ++ ctx_options |= SSL_OP_NO_SSLv2; ++ ctx_options |= SSL_OP_NO_SSLv3; ++ ctx_options |= SSL_OP_NO_TLSv1; ++ ctx_options |= SSL_OP_NO_TLSv1_2; ++ break; ++ case CURL_SSLVERSION_TLSv1_2: ++ ctx_options |= SSL_OP_NO_SSLv2; ++ ctx_options |= SSL_OP_NO_SSLv3; ++ ctx_options |= SSL_OP_NO_TLSv1; ++ ctx_options |= SSL_OP_NO_TLSv1_1; ++ break; ++ } + + SSL_CTX_set_options(connssl->ctx, ctx_options); + +diff --git a/packages/OS400/curl.inc.in b/packages/OS400/curl.inc.in +index 33ca12a..22a5511 100644 +--- a/packages/OS400/curl.inc.in ++++ b/packages/OS400/curl.inc.in +@@ -226,6 +226,12 @@ + d c 2 + d CURL_SSLVERSION_SSLv3... + d c 3 ++ d CURL_SSLVERSION_TLSv1_0... ++ d c 4 ++ d CURL_SSLVERSION_TLSv1_1... ++ d c 5 ++ d CURL_SSLVERSION_TLSv1_2... ++ d c 6 + * + d CURL_TLSAUTH_NONE... + d c 0 +diff --git a/src/tool_getparam.c b/src/tool_getparam.c +index 297b986..98d53a7 100644 +--- a/src/tool_getparam.c ++++ b/src/tool_getparam.c +@@ -175,6 +175,9 @@ static const struct LongShort aliases[]= { + {"$J", "metalink", FALSE}, + {"0", "http1.0", FALSE}, + {"1", "tlsv1", FALSE}, ++ {"10", "tlsv1.0", FALSE}, ++ {"11", "tlsv1.1", FALSE}, ++ {"12", "tlsv1.2", FALSE}, + {"2", "sslv2", FALSE}, + {"3", "sslv3", FALSE}, + {"4", "ipv4", FALSE}, +@@ -873,9 +876,25 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ + /* HTTP version 1.0 */ + config->httpversion = CURL_HTTP_VERSION_1_0; + break; +- case '1': +- /* TLS version 1 */ +- config->ssl_version = CURL_SSLVERSION_TLSv1; ++ case '1': /* --tlsv1* options */ ++ switch(subletter) { ++ case '\0': ++ /* TLS version 1.x */ ++ config->ssl_version = CURL_SSLVERSION_TLSv1; ++ break; ++ case '0': ++ /* TLS version 1.0 */ ++ config->ssl_version = CURL_SSLVERSION_TLSv1_0; ++ break; ++ case '1': ++ /* TLS version 1.1 */ ++ config->ssl_version = CURL_SSLVERSION_TLSv1_1; ++ break; ++ case '2': ++ /* TLS version 1.2 */ ++ config->ssl_version = CURL_SSLVERSION_TLSv1_2; ++ break; ++ } + break; + case '2': + /* SSL version 2 */ +diff --git a/src/tool_setopt.c b/src/tool_setopt.c +index 4014177..9860117 100644 +--- a/src/tool_setopt.c ++++ b/src/tool_setopt.c +@@ -78,6 +78,9 @@ const NameValue setopt_nv_CURL_SSLVERSION[] = { + NV(CURL_SSLVERSION_TLSv1), + NV(CURL_SSLVERSION_SSLv2), + NV(CURL_SSLVERSION_SSLv3), ++ NV(CURL_SSLVERSION_TLSv1_0), ++ NV(CURL_SSLVERSION_TLSv1_1), ++ NV(CURL_SSLVERSION_TLSv1_2), + NVEND, + }; + +-- +1.7.1 + + +From 350765306d7e2946fc8295fa2bfc2fe0c14651fc Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Tue, 15 Oct 2013 20:31:04 +0200 +Subject: [PATCH 2/9] curl: document the new --tlsv1.[012] options + +[upstream commit 076726f1412205622414abd908723c4b33ca12cb] +--- + docs/curl.1 | 20 ++++++++++++++++---- + 1 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/docs/curl.1 b/docs/curl.1 +index b350865..53b378c 100644 +--- a/docs/curl.1 ++++ b/docs/curl.1 +@@ -1419,14 +1419,26 @@ Set TLS authentication type. Currently, the only supported option is "SRP", + for TLS-SRP (RFC 5054). If \fI--tlsuser\fP and \fI--tlspassword\fP are + specified but \fI--tlsauthtype\fP is not, then this option defaults to "SRP". + (Added in 7.21.4) +-.IP "--tlsuser " +-Set username for use with the TLS authentication method specified with +-\fI--tlsauthtype\fP. Requires that \fI--tlspassword\fP also be set. (Added in +-7.21.4) + .IP "--tlspassword " + Set password for use with the TLS authentication method specified with + \fI--tlsauthtype\fP. Requires that \fI--tlsuser\fP also be set. (Added in + 7.21.4) ++.IP "--tlsuser " ++Set username for use with the TLS authentication method specified with ++\fI--tlsauthtype\fP. Requires that \fI--tlspassword\fP also be set. (Added in ++7.21.4) ++.IP "--tlsv1.0" ++(SSL) ++Forces curl to use TLS version 1.0 when negotiating with a remote TLS server. ++(Added in 7.34.0) ++.IP "--tlsv1.1" ++(SSL) ++Forces curl to use TLS version 1.1 when negotiating with a remote TLS server. ++(Added in 7.34.0) ++.IP "--tlsv1.2" ++(SSL) ++Forces curl to use TLS version 1.2 when negotiating with a remote TLS server. ++(Added in 7.34.0) + .IP "--tr-encoding" + (HTTP) Request a compressed Transfer-Encoding response using one of the + algorithms curl supports, and uncompress the data while receiving it. +-- +1.7.1 + + +From ba2b4e87b396faab9ccb5a3ca9aca935a7a78a1b Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Wed, 16 Oct 2013 20:06:23 +0100 +Subject: [PATCH 3/9] SSL: Corrected version number for new symbols from commit ad34a2d5c87c7f + +[upstream commit 2c84ffe1549ea7d5029ba7863f53013562e6758d] +--- + docs/libcurl/symbols-in-versions | 6 +++--- + 1 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions +index 57fa6eb..b275900 100644 +--- a/docs/libcurl/symbols-in-versions ++++ b/docs/libcurl/symbols-in-versions +@@ -678,9 +678,9 @@ CURL_SSLVERSION_DEFAULT 7.9.2 + CURL_SSLVERSION_SSLv2 7.9.2 + CURL_SSLVERSION_SSLv3 7.9.2 + CURL_SSLVERSION_TLSv1 7.9.2 +-CURL_SSLVERSION_TLSv1_0 7.33.0 +-CURL_SSLVERSION_TLSv1_1 7.33.0 +-CURL_SSLVERSION_TLSv1_2 7.33.0 ++CURL_SSLVERSION_TLSv1_0 7.34.0 ++CURL_SSLVERSION_TLSv1_1 7.34.0 ++CURL_SSLVERSION_TLSv1_2 7.34.0 + CURL_TIMECOND_IFMODSINCE 7.9.7 + CURL_TIMECOND_IFUNMODSINCE 7.9.7 + CURL_TIMECOND_LASTMOD 7.9.7 +-- +1.7.1 + + +From 5f908139b4e56c969bf6ef06c115a0a12353c827 Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Wed, 16 Oct 2013 20:18:15 +0100 +Subject: [PATCH 4/9] DOCS: Added libcurl version number to CURLOPT_SSLVERSION + +[upstream commit 75b9b26465d5f01b52564293c2d553649f801f70] +--- + docs/libcurl/curl_easy_setopt.3 | 8 +++++--- + 1 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 +index 92db8f4..d73b664 100644 +--- a/docs/libcurl/curl_easy_setopt.3 ++++ b/docs/libcurl/curl_easy_setopt.3 +@@ -2212,6 +2212,8 @@ Even though this option doesn't need any parameter, in some configurations + arguments. Therefore, it's recommended to pass 1 as parameter to this option. + .IP CURLOPT_SSLVERSION + Pass a long as parameter to control what version of SSL/TLS to attempt to use. ++(Added in 7.9.2) ++ + The available options are: + .RS + .IP CURL_SSLVERSION_DEFAULT +@@ -2225,11 +2227,11 @@ Force SSLv2 + .IP CURL_SSLVERSION_SSLv3 + Force SSLv3 + .IP CURL_SSLVERSION_TLSv1_0 +-Force TLSv1.0 ++Force TLSv1.0 (Added in 7.34.0) + .IP CURL_SSLVERSION_TLSv1_1 +-Force TLSv1.1 ++Force TLSv1.1 (Added in 7.34.0) + .IP CURL_SSLVERSION_TLSv1_2 +-Force TLSv1.2 ++Force TLSv1.2 (Added in 7.34.0) + .RE + .IP CURLOPT_SSL_VERIFYPEER + Pass a long as parameter. By default, curl assumes a value of 1. +-- +1.7.1 + + +From 7940044fc233f626b912b5f51a7a0111a4c145d3 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 25 Nov 2013 16:03:52 +0100 +Subject: [PATCH 5/9] nss: use a better API for controlling SSL version + +This change introduces a dependency on NSS 3.14+. + +[upstream commit 30e7e7552ba4397896ecac82ea04f38d52c4cc8f] +--- + configure | 20 ++++++++++---------- + configure.ac | 4 ++-- + docs/INTERNALS | 2 +- + lib/nss.c | 40 +++++++++++++++++++--------------------- + 4 files changed, 32 insertions(+), 34 deletions(-) + +diff --git a/configure b/configure +index 2496b3c..ebde78a 100755 +--- a/configure ++++ b/configure +@@ -23641,9 +23641,9 @@ $as_echo "found" >&6; } + CPPFLAGS="$CPPFLAGS $addcflags" + fi + +- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PK11_CreateGenericObject in -lnss3" >&5 +-$as_echo_n "checking for PK11_CreateGenericObject in -lnss3... " >&6; } +-if ${ac_cv_lib_nss3_PK11_CreateGenericObject+:} false; then : ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL_VersionRangeSet in -lnss3" >&5 ++$as_echo_n "checking for SSL_VersionRangeSet in -lnss3... " >&6; } ++if ${ac_cv_lib_nss3_SSL_VersionRangeSet+:} false; then : + $as_echo_n "(cached) " >&6 + else + ac_check_lib_save_LIBS=$LIBS +@@ -23655,26 +23655,26 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext + #ifdef __cplusplus + extern "C" + #endif +-char PK11_CreateGenericObject (); ++char SSL_VersionRangeSet (); + int main (void) + { +-return PK11_CreateGenericObject (); ++return SSL_VersionRangeSet (); + ; + return 0; + } + _ACEOF + if ac_fn_c_try_link "$LINENO"; then : +- ac_cv_lib_nss3_PK11_CreateGenericObject=yes ++ ac_cv_lib_nss3_SSL_VersionRangeSet=yes + else +- ac_cv_lib_nss3_PK11_CreateGenericObject=no ++ ac_cv_lib_nss3_SSL_VersionRangeSet=no + fi + rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS=$ac_check_lib_save_LIBS + fi +-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nss3_PK11_CreateGenericObject" >&5 +-$as_echo "$ac_cv_lib_nss3_PK11_CreateGenericObject" >&6; } +-if test "x$ac_cv_lib_nss3_PK11_CreateGenericObject" = xyes; then : ++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nss3_SSL_VersionRangeSet" >&5 ++$as_echo "$ac_cv_lib_nss3_SSL_VersionRangeSet" >&6; } ++if test "x$ac_cv_lib_nss3_SSL_VersionRangeSet" = xyes; then : + + + $as_echo "#define USE_NSS 1" >>confdefs.h +diff --git a/configure.ac b/configure.ac +index 5970188..c81c879 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2194,8 +2194,8 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then + CPPFLAGS="$CPPFLAGS $addcflags" + fi + +- dnl The function PK11_CreateGenericObject is needed to load libnsspem.so +- AC_CHECK_LIB(nss3, PK11_CreateGenericObject, ++ dnl The function SSL_VersionRangeSet() is needed to enable TLS > 1.0 ++ AC_CHECK_LIB(nss3, SSL_VersionRangeSet, + [ + AC_DEFINE(USE_NSS, 1, [if NSS is enabled]) + AC_SUBST(USE_NSS, [1]) +diff --git a/docs/INTERNALS b/docs/INTERNALS +index 03839c3..581b22d 100644 +--- a/docs/INTERNALS ++++ b/docs/INTERNALS +@@ -43,7 +43,7 @@ Portability + openldap 2.0 + MIT krb5 lib 1.2.4 + qsossl V5R2M0 +- NSS 3.12.x ++ NSS 3.14.x + axTLS 1.2.7 + Heimdal ? + +diff --git a/lib/nss.c b/lib/nss.c +index ff93a38..14a0b0c 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1175,9 +1175,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + { + PRErrorCode err = 0; + PRFileDesc *model = NULL; +- PRBool ssl2 = PR_FALSE; +- PRBool ssl3 = PR_FALSE; +- PRBool tlsv1 = PR_FALSE; ++ SSLVersionRange sslver; + PRBool ssl_no_cache; + PRBool ssl_cbc_random_iv; + struct SessionHandle *data = conn->data; +@@ -1251,20 +1249,25 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + switch (data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: +- ssl3 = PR_TRUE; +- if(data->state.ssl_connect_retry) ++ sslver.min = SSL_LIBRARY_VERSION_3_0; ++ if(data->state.ssl_connect_retry) { + infof(data, "TLS disabled due to previous handshake failure\n"); ++ sslver.max = SSL_LIBRARY_VERSION_3_0; ++ } + else +- tlsv1 = PR_TRUE; ++ sslver.max = SSL_LIBRARY_VERSION_TLS_1_0; + break; + case CURL_SSLVERSION_TLSv1: +- tlsv1 = PR_TRUE; ++ sslver.min = SSL_LIBRARY_VERSION_TLS_1_0; ++ sslver.max = SSL_LIBRARY_VERSION_TLS_1_0; + break; + case CURL_SSLVERSION_SSLv2: +- ssl2 = PR_TRUE; ++ sslver.min = SSL_LIBRARY_VERSION_2; ++ sslver.max = SSL_LIBRARY_VERSION_2; + break; + case CURL_SSLVERSION_SSLv3: +- ssl3 = PR_TRUE; ++ sslver.min = SSL_LIBRARY_VERSION_3_0; ++ sslver.max = SSL_LIBRARY_VERSION_3_0; + break; + case CURL_SSLVERSION_TLSv1_0: + case CURL_SSLVERSION_TLSv1_1: +@@ -1274,14 +1277,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + goto error; + } + +- if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess) +- goto error; +- if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess) +- goto error; +- if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess) +- goto error; +- +- if(SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess) ++ if(SSL_VersionRangeSet(model, &sslver) != SECSuccess) + goto error; + + ssl_cbc_random_iv = !data->set.ssl_enable_beast; +@@ -1467,11 +1463,13 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + if(model) + PR_Close(model); + +- /* cleanup on connection failure */ +- Curl_llist_destroy(connssl->obj_list, NULL); +- connssl->obj_list = NULL; ++ /* cleanup on connection failure */ ++ Curl_llist_destroy(connssl->obj_list, NULL); ++ connssl->obj_list = NULL; + +- if(ssl3 && tlsv1 && isTLSIntoleranceError(err)) { ++ 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"); +-- +1.7.1 + + +From 08398e7a8a8ba4e6fef1557392e3c0104cc3550f Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 25 Nov 2013 16:14:55 +0100 +Subject: [PATCH 6/9] nss: put SSL version selection into separate fnc + +[upstream commit 4fb8241add5b68e95fbf44d3c2bf470201a9915d] +--- + lib/nss.c | 72 +++++++++++++++++++++++++++++++++++------------------------- + 1 files changed, 42 insertions(+), 30 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 14a0b0c..2e2240b 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1171,6 +1171,46 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn, + return CURLE_OK; + } + ++static CURLcode nss_init_sslver(SSLVersionRange *sslver, ++ struct SessionHandle *data) ++{ ++ switch (data->set.ssl.version) { ++ default: ++ case CURL_SSLVERSION_DEFAULT: ++ sslver->min = SSL_LIBRARY_VERSION_3_0; ++ if(data->state.ssl_connect_retry) { ++ infof(data, "TLS disabled due to previous handshake failure\n"); ++ sslver->max = SSL_LIBRARY_VERSION_3_0; ++ } ++ else ++ sslver->max = SSL_LIBRARY_VERSION_TLS_1_0; ++ return CURLE_OK; ++ ++ case CURL_SSLVERSION_TLSv1: ++ sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; ++ sslver->max = SSL_LIBRARY_VERSION_TLS_1_0; ++ return CURLE_OK; ++ ++ case CURL_SSLVERSION_SSLv2: ++ sslver->min = SSL_LIBRARY_VERSION_2; ++ sslver->max = SSL_LIBRARY_VERSION_2; ++ return CURLE_OK; ++ ++ case CURL_SSLVERSION_SSLv3: ++ sslver->min = SSL_LIBRARY_VERSION_3_0; ++ sslver->max = SSL_LIBRARY_VERSION_3_0; ++ return CURLE_OK; ++ ++ case CURL_SSLVERSION_TLSv1_0: ++ case CURL_SSLVERSION_TLSv1_1: ++ case CURL_SSLVERSION_TLSv1_2: ++ break; ++ } ++ ++ failf(data, "TLS minor version cannot be set"); ++ return CURLE_SSL_CONNECT_ERROR; ++} ++ + CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + { + PRErrorCode err = 0; +@@ -1246,37 +1286,9 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess) + goto error; + +- switch (data->set.ssl.version) { +- default: +- case CURL_SSLVERSION_DEFAULT: +- sslver.min = SSL_LIBRARY_VERSION_3_0; +- if(data->state.ssl_connect_retry) { +- infof(data, "TLS disabled due to previous handshake failure\n"); +- sslver.max = SSL_LIBRARY_VERSION_3_0; +- } +- else +- sslver.max = SSL_LIBRARY_VERSION_TLS_1_0; +- break; +- case CURL_SSLVERSION_TLSv1: +- sslver.min = SSL_LIBRARY_VERSION_TLS_1_0; +- sslver.max = SSL_LIBRARY_VERSION_TLS_1_0; +- break; +- case CURL_SSLVERSION_SSLv2: +- sslver.min = SSL_LIBRARY_VERSION_2; +- sslver.max = SSL_LIBRARY_VERSION_2; +- break; +- case CURL_SSLVERSION_SSLv3: +- sslver.min = SSL_LIBRARY_VERSION_3_0; +- sslver.max = SSL_LIBRARY_VERSION_3_0; +- break; +- case CURL_SSLVERSION_TLSv1_0: +- case CURL_SSLVERSION_TLSv1_1: +- case CURL_SSLVERSION_TLSv1_2: +- failf(data, "TLS minor version cannot be set\n"); +- curlerr = CURLE_SSL_CONNECT_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; + +-- +1.7.1 + + +From 91a3d58fc48f0d08ab81f1e013b2d58a7ccd7146 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 25 Nov 2013 16:25:15 +0100 +Subject: [PATCH 7/9] nss: allow to use TLS > 1.0 if built against recent NSS + +Bug: http://curl.haxx.se/mail/lib-2013-11/0162.html + +[upstream commit 7fc9325a52a6dad1f8b859a3269472ffc125edd0] +--- + lib/nss.c | 22 ++++++++++++++++++++++ + 1 files changed, 22 insertions(+), 0 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 2e2240b..5cd33d8 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1188,7 +1188,13 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver, + + case CURL_SSLVERSION_TLSv1: + sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; ++#ifdef SSL_LIBRARY_VERSION_TLS_1_2 ++ sslver->max = SSL_LIBRARY_VERSION_TLS_1_2; ++#elif defined SSL_LIBRARY_VERSION_TLS_1_1 ++ sslver->max = SSL_LIBRARY_VERSION_TLS_1_1; ++#else + sslver->max = SSL_LIBRARY_VERSION_TLS_1_0; ++#endif + return CURLE_OK; + + case CURL_SSLVERSION_SSLv2: +@@ -1202,8 +1208,24 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver, + return CURLE_OK; + + case CURL_SSLVERSION_TLSv1_0: ++ sslver->min = SSL_LIBRARY_VERSION_TLS_1_0; ++ sslver->max = SSL_LIBRARY_VERSION_TLS_1_0; ++ return CURLE_OK; ++ + case CURL_SSLVERSION_TLSv1_1: ++#ifdef SSL_LIBRARY_VERSION_TLS_1_1 ++ sslver->min = SSL_LIBRARY_VERSION_TLS_1_1; ++ sslver->max = SSL_LIBRARY_VERSION_TLS_1_1; ++ return CURLE_OK; ++#endif ++ break; ++ + case CURL_SSLVERSION_TLSv1_2: ++#ifdef SSL_LIBRARY_VERSION_TLS_1_2 ++ sslver->min = SSL_LIBRARY_VERSION_TLS_1_2; ++ sslver->max = SSL_LIBRARY_VERSION_TLS_1_2; ++ return CURLE_OK; ++#endif + break; + } + +-- +1.7.1 + + +From 404492a5a815b83fab58ce60434c01c270b6bc73 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 2 Dec 2013 14:25:07 +0100 +Subject: [PATCH 8/9] nss: unconditionally require NSS_InitContext() + +... since we depend on NSS 3.14+ because of SSL_VersionRangeSet() anyway + +[upstream commit 865666afca926faa1c721020fc54364540caf734] +--- + configure | 12 ------------ + configure.ac | 8 -------- + lib/nss.c | 26 -------------------------- + 3 files changed, 0 insertions(+), 46 deletions(-) + +diff --git a/configure b/configure +index ebde78a..8741e21 100755 +--- a/configure ++++ b/configure +@@ -23697,18 +23697,6 @@ fi + { $as_echo "$as_me:${as_lineno-$LINENO}: detected NSS version $version" >&5 + $as_echo "$as_me: detected NSS version $version" >&6;} + +- ac_fn_c_check_func "$LINENO" "NSS_InitContext" "ac_cv_func_NSS_InitContext" +-if test "x$ac_cv_func_NSS_InitContext" = xyes; then : +- +- +-$as_echo "#define HAVE_NSS_INITCONTEXT 1" >>confdefs.h +- +- HAVE_NSS_INITCONTEXT=1 +- +- +-fi +- +- + 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 c81c879..70ef0b7 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2211,14 +2211,6 @@ if test "$curl_ssl_msg" = "$init_ssl_msg"; then + if test "x$USE_NSS" = "xyes"; then + AC_MSG_NOTICE([detected NSS version $version]) + +- dnl NSS_InitContext() was introduced in NSS 3.12.5 and helps to prevent +- dnl collisions on NSS initialization/shutdown with other libraries +- AC_CHECK_FUNC(NSS_InitContext, +- [ +- AC_DEFINE(HAVE_NSS_INITCONTEXT, 1, [if you have the NSS_InitContext function]) +- AC_SUBST(HAVE_NSS_INITCONTEXT, [1]) +- ]) +- + 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/lib/nss.c b/lib/nss.c +index 5cd33d8..7b49c20 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -76,9 +76,7 @@ PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd); + + PRLock * nss_initlock = NULL; + PRLock * nss_crllock = NULL; +-#ifdef HAVE_NSS_INITCONTEXT + NSSInitContext * nss_context = NULL; +-#endif + + volatile int initialized = 0; + +@@ -853,7 +851,6 @@ isTLSIntoleranceError(PRInt32 err) + + static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) + { +-#ifdef HAVE_NSS_INITCONTEXT + NSSInitParameters initparams; + + if(nss_context != NULL) +@@ -861,12 +858,6 @@ static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) + + memset((void *) &initparams, '\0', sizeof(initparams)); + initparams.length = sizeof(initparams); +-#else /* HAVE_NSS_INITCONTEXT */ +- SECStatus rv; +- +- if(NSS_IsInitialized()) +- return CURLE_OK; +-#endif + + if(cert_dir) { + const bool use_sql = NSS_VersionCheck("3.12.0"); +@@ -875,35 +866,22 @@ static CURLcode nss_init_core(struct SessionHandle *data, const char *cert_dir) + return CURLE_OUT_OF_MEMORY; + + infof(data, "Initializing NSS with certpath: %s\n", certpath); +-#ifdef HAVE_NSS_INITCONTEXT + nss_context = NSS_InitContext(certpath, "", "", "", &initparams, + NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); + free(certpath); + + if(nss_context != NULL) + return CURLE_OK; +-#else /* HAVE_NSS_INITCONTEXT */ +- rv = NSS_Initialize(certpath, "", "", "", NSS_INIT_READONLY); +- free(certpath); +- +- if(rv == SECSuccess) +- return CURLE_OK; +-#endif + + infof(data, "Unable to initialize NSS database\n"); + } + + infof(data, "Initializing NSS with certpath: none\n"); +-#ifdef HAVE_NSS_INITCONTEXT + nss_context = NSS_InitContext("", "", "", "", &initparams, NSS_INIT_READONLY + | NSS_INIT_NOCERTDB | NSS_INIT_NOMODDB | NSS_INIT_FORCEOPEN + | NSS_INIT_NOROOTINIT | NSS_INIT_OPTIMIZESPACE | NSS_INIT_PK11RELOAD); + if(nss_context != NULL) + return CURLE_OK; +-#else /* HAVE_NSS_INITCONTEXT */ +- if(NSS_NoDB_Init(NULL) == SECSuccess) +- return CURLE_OK; +-#endif + + infof(data, "Unable to initialize NSS\n"); + return CURLE_SSL_CACERT_BADFILE; +@@ -999,12 +977,8 @@ void Curl_nss_cleanup(void) + SECMOD_DestroyModule(mod); + mod = NULL; + } +-#ifdef HAVE_NSS_INITCONTEXT + NSS_ShutdownContext(nss_context); + nss_context = NULL; +-#else /* HAVE_NSS_INITCONTEXT */ +- NSS_Shutdown(); +-#endif + } + PR_Unlock(nss_initlock); + +-- +1.7.1 + + +From a643c75662b6909a5be1bed8273ed1273ab2b3f4 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 2 Dec 2013 16:09:12 +0100 +Subject: [PATCH 9/9] nss: make sure that 'sslver' is always initialized + +[upstream commit e221b55f67a2e12717e911f25d1bb6c85fcebfab] +--- + lib/nss.c | 9 +++++---- + 1 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 7b49c20..abc8a91 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1151,13 +1151,10 @@ static CURLcode nss_init_sslver(SSLVersionRange *sslver, + switch (data->set.ssl.version) { + default: + case CURL_SSLVERSION_DEFAULT: +- sslver->min = SSL_LIBRARY_VERSION_3_0; + if(data->state.ssl_connect_retry) { + infof(data, "TLS disabled due to previous handshake failure\n"); + sslver->max = SSL_LIBRARY_VERSION_3_0; + } +- else +- sslver->max = SSL_LIBRARY_VERSION_TLS_1_0; + return CURLE_OK; + + case CURL_SSLVERSION_TLSv1: +@@ -1211,7 +1208,6 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + { + PRErrorCode err = 0; + PRFileDesc *model = NULL; +- SSLVersionRange sslver; + PRBool ssl_no_cache; + PRBool ssl_cbc_random_iv; + struct SessionHandle *data = conn->data; +@@ -1223,6 +1219,11 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex) + long time_left; + PRUint32 timeout; + ++ SSLVersionRange sslver = { ++ SSL_LIBRARY_VERSION_3_0, /* min */ ++ SSL_LIBRARY_VERSION_TLS_1_0 /* max */ ++ }; ++ + if(connssl->state == ssl_connection_complete) + return CURLE_OK; + +-- +1.7.1 + diff --git a/SOURCES/0016-curl-7.29.0-1cf71bd7.patch b/SOURCES/0016-curl-7.29.0-1cf71bd7.patch new file mode 100644 index 0000000..31c4e08 --- /dev/null +++ b/SOURCES/0016-curl-7.29.0-1cf71bd7.patch @@ -0,0 +1,27 @@ +From cf8b6a21f1e9af984cfef417e83ca06b64565215 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 20 Jan 2014 20:24:05 +0100 +Subject: [PATCH] Curl_is_connected: use proxy name in error message when proxy is used + +Backport of upstream commit 1cf71bd76e4a330e5b7824014c2605e4bfe1a0a5. +--- + lib/connect.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/lib/connect.c b/lib/connect.c +index 0afb1ee..ba9ab92 100644 +--- a/lib/connect.c ++++ b/lib/connect.c +@@ -758,7 +758,8 @@ CURLcode Curl_is_connected(struct connectdata *conn, + error = SOCKERRNO; + data->state.os_errno = error; + failf(data, "Failed connect to %s:%ld; %s", +- conn->host.name, conn->port, Curl_strerror(conn, error)); ++ conn->bits.proxy?conn->proxy.name:conn->host.name, ++ conn->port, Curl_strerror(conn, error)); + } + + return code; +-- +1.7.1 + diff --git a/SOURCES/0017-curl-7.29.0-ffb8a21d.patch b/SOURCES/0017-curl-7.29.0-ffb8a21d.patch new file mode 100644 index 0000000..5f35a9a --- /dev/null +++ b/SOURCES/0017-curl-7.29.0-ffb8a21d.patch @@ -0,0 +1,36 @@ +From 93b06606d7ee483567770deda967985e8377debb Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sun, 2 Feb 2014 11:01:10 +0000 +Subject: [PATCH] tests: Fixed test172 cookie expiry + +The test contains a cookie jar file where one of the cookies has an +expiry date of 1391252187 -- Sat, 1 Feb 2014 10:56:27 GMT which has +now expired. Updated to Wed, 14 Oct 2037 16:36:33 GMT as per test +179. + +Reported-by: Adam Sampson +Bug: http://curl.haxx.se/bug/view.cgi?id=1330 + +[upstream commit ffb8a21d85bde8b626e5dc52ce25f0447ee49f89] + +Signed-off-by: Kamil Dudka +--- + tests/data/test172 | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/tests/data/test172 b/tests/data/test172 +index b3efae9..3d53418 100644 +--- a/tests/data/test172 ++++ b/tests/data/test172 +@@ -36,7 +36,7 @@ http://%HOSTIP:%HTTPPORT/we/want/172 -b log/jar172.txt -b "tool=curl; name=fool" + + .%HOSTIP TRUE /silly/ FALSE 0 ismatch this + .%HOSTIP TRUE / FALSE 0 partmatch present +-%HOSTIP FALSE /we/want/ FALSE 1391252187 nodomain value ++%HOSTIP FALSE /we/want/ FALSE 2139150993 nodomain value + + + +-- +1.7.1 + diff --git a/SOURCES/0018-curl-7.29.0-03c28820.patch b/SOURCES/0018-curl-7.29.0-03c28820.patch new file mode 100644 index 0000000..09a7391 --- /dev/null +++ b/SOURCES/0018-curl-7.29.0-03c28820.patch @@ -0,0 +1,67 @@ +From fbbbf6a3daa7949cfb0fbd9731a80649ce717e6d Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 7 Feb 2014 20:28:53 +0100 +Subject: [PATCH 1/2] --help: add missing --tlsv1.x options + +[upstream commit 67d14ab98f8b819ee6f5e6a4a2770d311c6bf13b] + +Signed-off-by: Kamil Dudka +--- + src/tool_help.c | 5 ++++- + 1 files changed, 4 insertions(+), 1 deletions(-) + +diff --git a/src/tool_help.c b/src/tool_help.c +index 124f640..f7cd618 100644 +--- a/src/tool_help.c ++++ b/src/tool_help.c +@@ -199,7 +199,10 @@ static const char *const helptext[] = { + " -t, --telnet-option OPT=VAL Set telnet option", + " --tftp-blksize VALUE Set TFTP BLKSIZE option (must be >512)", + " -z, --time-cond TIME Transfer based on a time condition", +- " -1, --tlsv1 Use TLSv1 (SSL)", ++ " -1, --tlsv1 Use => TLSv1 (SSL)", ++ " --tlsv1.0 Use TLSv1.0 (SSL)", ++ " --tlsv1.1 Use TLSv1.1 (SSL)", ++ " --tlsv1.2 Use TLSv1.2 (SSL)", + " --trace FILE Write a debug trace to the given file", + " --trace-ascii FILE Like --trace but without the hex output", + " --trace-time Add time stamps to trace/verbose output", +-- +1.7.1 + + +From cc28ee70fcc2222646eef4f2b2ab3cc207c6112a Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 17 Feb 2014 16:55:10 +0100 +Subject: [PATCH 2/2] curl.1: update the description of --tlsv1 + +... and mention the --tlsv1.[0-2] options in the --tslv1 entry + +Reported-by: Hubert Kario + +[upstream commit 03c288202ed159a2a9e953f59e58f69a86eda79b] + +Signed-off-by: Kamil Dudka +--- + docs/curl.1 | 5 ++++- + 1 files changed, 4 insertions(+), 1 deletions(-) + +diff --git a/docs/curl.1 b/docs/curl.1 +index 53b378c..7f3571b 100644 +--- a/docs/curl.1 ++++ b/docs/curl.1 +@@ -117,7 +117,10 @@ more informational, meter. + internally preferred: HTTP 1.1. + .IP "-1, --tlsv1" + (SSL) +-Forces curl to use TLS version 1 when negotiating with a remote TLS server. ++Forces curl to use TLS version 1.x when negotiating with a remote TLS server. ++You can use options \fI--tlsv1.0\fP, \fI--tlsv1.1\fP, and \fI--tlsv1.2\fP to ++control the TLS version more precisely (if the SSL backend in use supports such ++a level of control). + .IP "-2, --sslv2" + (SSL) + Forces curl to use SSL version 2 when negotiating with a remote SSL server. +-- +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..777e8b8 --- /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 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)) { + /* 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..7ed2377 --- /dev/null +++ b/SOURCES/0022-curl-7.29.0-24c3cdce.patch @@ -0,0 +1,237 @@ +From ca7b1cd659eb0eb0ef355e3e122742abcea73287 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 2 Jul 2014 16:34:48 +0200 +Subject: [PATCH 1/3] 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/3] 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 + + +From 0631da3859c9868ff317521544a246b5be83e600 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Tue, 14 Jul 2015 17:08:44 +0200 +Subject: [PATCH 3/3] libtest: call PR_Cleanup() on exit if NSPR is used +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This prevents valgrind from reporting possibly lost memory that NSPR +uses for file descriptor cache and other globally allocated internal +data structures. + +Reported-by: Štefan Kremeň + +Upstream-commit: cd20e81e89ecebc5064e1d3e22e62e2802b2711e +Signed-off-by: Kamil Dudka +--- + tests/libtest/Makefile.am | 4 ++-- + tests/libtest/Makefile.in | 4 ++-- + tests/libtest/first.c | 15 ++++++++++++++- + 3 files changed, 18 insertions(+), 5 deletions(-) + +diff --git a/tests/libtest/Makefile.am b/tests/libtest/Makefile.am +index ba4097f..a844ab2 100644 +--- a/tests/libtest/Makefile.am ++++ b/tests/libtest/Makefile.am +@@ -62,8 +62,8 @@ if USE_EXPLICIT_LIB_DEPS + SUPPORTFILES_LIBS = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@ + TESTUTIL_LIBS = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@ + else +-SUPPORTFILES_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_LIBS@ +-TESTUTIL_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_AND_TIME_LIBS@ ++SUPPORTFILES_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_LIBS@ @NSS_LIBS@ ++TESTUTIL_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_AND_TIME_LIBS@ @NSS_LIBS@ + endif + + # Dependencies (may need to be overriden) +diff --git a/tests/libtest/Makefile.in b/tests/libtest/Makefile.in +index e6826c0..9086af3 100644 +--- a/tests/libtest/Makefile.in ++++ b/tests/libtest/Makefile.in +@@ -949,9 +949,9 @@ AUTOMAKE_OPTIONS = foreign nostdinc + EXTRA_DIST = test75.pl test307.pl test610.pl test613.pl test1013.pl \ + test1022.pl Makefile.inc notexists.pl + +-@USE_EXPLICIT_LIB_DEPS_FALSE@SUPPORTFILES_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_LIBS@ ++@USE_EXPLICIT_LIB_DEPS_FALSE@SUPPORTFILES_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_LIBS@ @NSS_LIBS@ + @USE_EXPLICIT_LIB_DEPS_TRUE@SUPPORTFILES_LIBS = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@ +-@USE_EXPLICIT_LIB_DEPS_FALSE@TESTUTIL_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_AND_TIME_LIBS@ ++@USE_EXPLICIT_LIB_DEPS_FALSE@TESTUTIL_LIBS = $(top_builddir)/lib/libcurl.la @CURL_NETWORK_AND_TIME_LIBS@ @NSS_LIBS@ + @USE_EXPLICIT_LIB_DEPS_TRUE@TESTUTIL_LIBS = $(top_builddir)/lib/libcurl.la @LIBCURL_LIBS@ + + # Dependencies (may need to be overriden) +diff --git a/tests/libtest/first.c b/tests/libtest/first.c +index 253acb2..94748a5 100644 +--- a/tests/libtest/first.c ++++ b/tests/libtest/first.c +@@ -25,6 +25,10 @@ + #include /* for setlocale() */ + #endif + ++#ifdef USE_NSS ++#include ++#endif ++ + #ifdef CURLDEBUG + # define MEMDEBUG_NODEFINES + # include "memdebug.h" +@@ -97,6 +101,7 @@ static void memory_tracking_init(void) + int main(int argc, char **argv) + { + char *URL; ++ int result; + + memory_tracking_init(); + +@@ -127,5 +132,13 @@ int main(int argc, char **argv) + + fprintf(stderr, "URL: %s\n", URL); + +- return test(URL); ++ result = test(URL); ++ ++#ifdef USE_NSS ++ if(PR_Initialized()) ++ /* prevent valgrind from reporting possibly lost memory (fd cache, ...) */ ++ PR_Cleanup(); ++#endif ++ ++ return result; + } +-- +2.4.3 + 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..6ccba89 --- /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..c69af4a --- /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 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) || +-- +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/0034-curl-7.29.0-002d58f1.patch b/SOURCES/0034-curl-7.29.0-002d58f1.patch new file mode 100644 index 0000000..820cfe7 --- /dev/null +++ b/SOURCES/0034-curl-7.29.0-002d58f1.patch @@ -0,0 +1,42 @@ +From c90b930b8312bb31f62325a09125cf44dd58d506 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Mon, 10 Aug 2015 00:12:12 +0200 +Subject: [PATCH] test46: update cookie expire time + +... since it went old and thus was expired and caused the test to fail! + +Upstream-commit: 002d58f1e8d8e725ba6d676599838983561feff9 +Signed-off-by: Kamil Dudka +--- + tests/data/test46 | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/tests/data/test46 b/tests/data/test46 +index b6f8f83..b6ebe80 100644 +--- a/tests/data/test46 ++++ b/tests/data/test46 +@@ -51,8 +51,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 /want FALSE 1439150993 mooo2 indeed2 ++%HOSTIP FALSE / FALSE 1739150993 mooo indeed ++#HttpOnly_%HOSTIP FALSE /want FALSE 1739150993 mooo2 indeed2 + %HOSTIP FALSE /want FALSE 0 empty + + +@@ -76,8 +76,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 /want FALSE 1439150993 mooo2 indeed2 ++%HOSTIP FALSE / FALSE 1739150993 mooo indeed ++#HttpOnly_%HOSTIP FALSE /want FALSE 1739150993 mooo2 indeed2 + %HOSTIP FALSE /want FALSE 0 empty + %HOSTIP FALSE / FALSE 2054030187 ckyPersistent permanent + %HOSTIP FALSE / FALSE 0 ckySession temporary +-- +2.4.6 + diff --git a/SOURCES/0035-curl-7.29.0-2f1a0bc0.patch b/SOURCES/0035-curl-7.29.0-2f1a0bc0.patch new file mode 100644 index 0000000..515c92a --- /dev/null +++ b/SOURCES/0035-curl-7.29.0-2f1a0bc0.patch @@ -0,0 +1,2989 @@ +From 965f26c806a87fbf9ae803d12d57b1e5f91e0754 Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sat, 13 Apr 2013 10:49:42 +0100 +Subject: [PATCH 01/28] url: Added support for parsing login options from the + URL + +As well as parsing the username and password from the URL, added support +for parsing the optional options part from the login details, to allow +the following supported URL format: + +schema://username:password;options@example.com/path?q=foobar + +This will only be used by IMAP, POP3 and SMTP at present but any +protocol that may be given login options in the URL will be able to +add support for them. + +Upstream-commit: 73aa95592f47d461f0246eef1187f5d569aa6afa +Signed-off-by: Kamil Dudka +--- + lib/url.c | 79 ++++++++++++++++++++++++++++++++++++++++++++--------------- + lib/urldata.h | 3 +++ + 2 files changed, 62 insertions(+), 20 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 2dc56ae..fdf6bca 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -2461,6 +2461,7 @@ static void conn_free(struct connectdata *conn) + + Curl_safefree(conn->user); + Curl_safefree(conn->passwd); ++ Curl_safefree(conn->options); + Curl_safefree(conn->proxyuser); + Curl_safefree(conn->proxypasswd); + Curl_safefree(conn->allocptr.proxyuserpwd); +@@ -4283,24 +4284,27 @@ static CURLcode parse_url_userpass(struct SessionHandle *data, + struct connectdata *conn, + char *user, char *passwd) + { ++ char options[MAX_CURL_OPTIONS_LENGTH]; ++ + /* At this point, we're hoping all the other special cases have + * been taken care of, so conn->host.name is at most +- * [user[:password]]@]hostname ++ * [user[:password][;options]]@]hostname + * + * We need somewhere to put the embedded details, so do that first. + */ + +- char *ptr=strchr(conn->host.name, '@'); ++ char *ptr = strchr(conn->host.name, '@'); + char *userpass = conn->host.name; + +- user[0] =0; /* to make everything well-defined */ +- passwd[0]=0; ++ user[0] = 0; /* to make everything well-defined */ ++ passwd[0] = 0; ++ options[0] = 0; + + /* We will now try to extract the +- * possible user+password pair in a string like: ++ * possible login information in a string like: + * ftp://user:password@ftp.my.site:8021/README */ + if(ptr != NULL) { +- /* there's a user+password given here, to the left of the @ */ ++ /* There's login information to the left of the @ */ + + conn->host.name = ++ptr; + +@@ -4310,26 +4314,46 @@ static CURLcode parse_url_userpass(struct SessionHandle *data, + * set user/passwd, but doing that first adds more cases here :-( + */ + +- conn->bits.userpwd_in_url = TRUE; + if(data->set.use_netrc != CURL_NETRC_REQUIRED) { +- /* We could use the one in the URL */ +- +- conn->bits.user_passwd = TRUE; /* enable user+password */ +- ++ /* We could use the information in the URL so extract it */ + if(*userpass != ':') { +- /* the name is given, get user+password */ +- sscanf(userpass, "%" MAX_CURL_USER_LENGTH_TXT "[^:@]:" +- "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]", +- user, passwd); ++ if(*userpass != ';') { ++ /* The user is given so extract the user, password and options */ ++ int result = sscanf(userpass, ++ "%" MAX_CURL_USER_LENGTH_TXT "[^:;@]:" ++ "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^;@];" ++ "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", ++ user, passwd, options); ++ ++ /* The extract failed so extract the user and options instead */ ++ if(result == 1) ++ sscanf(userpass, "%" MAX_CURL_USER_LENGTH_TXT "[^:;@];" ++ "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", ++ user, options); ++ } ++ else { ++ /* No name or password are given so extract the options only */ ++ sscanf(userpass, ";%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", options); ++ } + } + else +- /* no name given, get the password only */ +- sscanf(userpass, ":%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]", passwd); ++ /* No name is given so extract the password and options */ ++ sscanf(userpass, ":%" MAX_CURL_PASSWORD_LENGTH_TXT "[^;@];" ++ "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", ++ passwd, options); + + if(user[0]) { +- char *newname=curl_easy_unescape(data, user, 0, NULL); ++ char *newname; ++ ++ /* We have a user in the URL */ ++ conn->bits.userpwd_in_url = TRUE; ++ conn->bits.user_passwd = TRUE; /* enable user+password */ ++ ++ /* Decode the user */ ++ newname = curl_easy_unescape(data, user, 0, NULL); + if(!newname) + return CURLE_OUT_OF_MEMORY; ++ + if(strlen(newname) < MAX_CURL_USER_LENGTH) + strcpy(user, newname); + +@@ -4337,18 +4361,33 @@ static CURLcode parse_url_userpass(struct SessionHandle *data, + the unconverted name, it'll be wrong but what the heck */ + free(newname); + } ++ + if(passwd[0]) { +- /* we have a password found in the URL, decode it! */ +- char *newpasswd=curl_easy_unescape(data, passwd, 0, NULL); ++ /* We have a password in the URL so decode it */ ++ char *newpasswd = curl_easy_unescape(data, passwd, 0, NULL); + if(!newpasswd) + return CURLE_OUT_OF_MEMORY; ++ + if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH) + strcpy(passwd, newpasswd); + + free(newpasswd); + } ++ ++ if(options[0]) { ++ /* We have an options list in the URL so decode it */ ++ char *newoptions = curl_easy_unescape(data, options, 0, NULL); ++ if(!newoptions) ++ return CURLE_OUT_OF_MEMORY; ++ ++ if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH) ++ conn->options = newoptions; ++ else ++ free(newoptions); ++ } + } + } ++ + return CURLE_OK; + } + +diff --git a/lib/urldata.h b/lib/urldata.h +index 26bc89f..46ef5d5 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -847,6 +847,7 @@ struct connectdata { + + char *user; /* user name string, allocated */ + char *passwd; /* password string, allocated */ ++ char *options; /* options string, allocated */ + + char *proxyuser; /* proxy user name string, allocated */ + char *proxypasswd; /* proxy password string, allocated */ +@@ -1132,8 +1133,10 @@ typedef enum { + * Session-data MUST be put in the connectdata struct and here. */ + #define MAX_CURL_USER_LENGTH 256 + #define MAX_CURL_PASSWORD_LENGTH 256 ++#define MAX_CURL_OPTIONS_LENGTH 256 + #define MAX_CURL_USER_LENGTH_TXT "255" + #define MAX_CURL_PASSWORD_LENGTH_TXT "255" ++#define MAX_CURL_OPTIONS_LENGTH_TXT "255" + + struct auth { + unsigned long want; /* Bitmask set to the authentication methods wanted by +-- +2.4.6 + + +From 8e092594b858dd049e3f4f6660325f703e0a1c44 Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Thu, 18 Apr 2013 17:02:28 +0100 +Subject: [PATCH 02/28] url: Reworked URL parsing to allow overriding by + CURLOPT_USERPWD + +Upstream-commit: 90c87f311eb087840008bfe89b19e6e0b808a246 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 50 +++++++++++++++++++++++++++++++------------------- + 1 file changed, 31 insertions(+), 19 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index fdf6bca..4a9df84 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -140,7 +140,7 @@ static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke); + static CURLcode do_init(struct connectdata *conn); + static CURLcode parse_url_userpass(struct SessionHandle *data, + struct connectdata *conn, +- char *user, char *passwd); ++ char *user, char *passwd, char *options); + /* + * Protocol table. + */ +@@ -3585,8 +3585,7 @@ static CURLcode findprotocol(struct SessionHandle *data, + static CURLcode parseurlandfillconn(struct SessionHandle *data, + struct connectdata *conn, + bool *prot_missing, +- char *user, +- char *passwd) ++ char *user, char *passwd, char *options) + { + char *at; + char *fragment; +@@ -3811,7 +3810,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data, + * Parse a user name and password in the URL and strip it out + * of the host name + *************************************************************/ +- result = parse_url_userpass(data, conn, user, passwd); ++ result = parse_url_userpass(data, conn, user, passwd, options); + if(result != CURLE_OK) + return result; + +@@ -4282,10 +4281,8 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data, + */ + static CURLcode parse_url_userpass(struct SessionHandle *data, + struct connectdata *conn, +- char *user, char *passwd) ++ char *user, char *passwd, char *options) + { +- char options[MAX_CURL_OPTIONS_LENGTH]; +- + /* At this point, we're hoping all the other special cases have + * been taken care of, so conn->host.name is at most + * [user[:password][;options]]@]hostname +@@ -4381,9 +4378,9 @@ static CURLcode parse_url_userpass(struct SessionHandle *data, + return CURLE_OUT_OF_MEMORY; + + if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH) +- conn->options = newoptions; +- else +- free(newoptions); ++ strcpy(options, newoptions); ++ ++ free(newoptions); + } + } + } +@@ -4551,11 +4548,13 @@ static void override_userpass(struct SessionHandle *data, + * Set password so it's available in the connection. + */ + static CURLcode set_userpass(struct connectdata *conn, +- const char *user, const char *passwd) ++ const char *user, const char *passwd, ++ const char *options) + { ++ CURLcode result = CURLE_OK; ++ + /* If our protocol needs a password and we have none, use the defaults */ +- if((conn->handler->flags & PROTOPT_NEEDSPWD) && +- !conn->bits.user_passwd) { ++ if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) { + + conn->user = strdup(CURL_DEFAULT_USER); + if(conn->user) +@@ -4565,17 +4564,28 @@ static CURLcode set_userpass(struct connectdata *conn, + /* This is the default password, so DON'T set conn->bits.user_passwd */ + } + else { +- /* store user + password, zero-length if not set */ ++ /* Store the user, zero-length if not set */ + conn->user = strdup(user); ++ ++ /* Store the password (only if user is present), zero-length if not set */ + if(conn->user) + conn->passwd = strdup(passwd); + else + conn->passwd = NULL; + } ++ + if(!conn->user || !conn->passwd) +- return CURLE_OUT_OF_MEMORY; ++ result = CURLE_OUT_OF_MEMORY; + +- return CURLE_OK; ++ /* Store the options, null if not set */ ++ if(!result && options[0]) { ++ conn->options = strdup(options); ++ ++ if(!conn->options) ++ result = CURLE_OUT_OF_MEMORY; ++ } ++ ++ return result; + } + + /************************************************************* +@@ -4745,12 +4755,13 @@ static CURLcode create_conn(struct SessionHandle *data, + struct connectdata **in_connect, + bool *async) + { +- CURLcode result=CURLE_OK; ++ CURLcode result = CURLE_OK; + struct connectdata *conn; + struct connectdata *conn_temp = NULL; + size_t urllen; + char user[MAX_CURL_USER_LENGTH]; + char passwd[MAX_CURL_PASSWORD_LENGTH]; ++ char options[MAX_CURL_OPTIONS_LENGTH]; + bool reuse; + char *proxy = NULL; + bool prot_missing = FALSE; +@@ -4815,7 +4826,8 @@ static CURLcode create_conn(struct SessionHandle *data, + conn->host.name = conn->host.rawalloc; + conn->host.name[0] = 0; + +- result = parseurlandfillconn(data, conn, &prot_missing, user, passwd); ++ result = parseurlandfillconn(data, conn, &prot_missing, user, passwd, ++ options); + if(result != CURLE_OK) + return result; + +@@ -5016,7 +5028,7 @@ static CURLcode create_conn(struct SessionHandle *data, + * for use + *************************************************************/ + override_userpass(data, conn, user, passwd); +- result = set_userpass(conn, user, passwd); ++ result = set_userpass(conn, user, passwd, options); + if(result != CURLE_OK) + return result; + +-- +2.4.6 + + +From c9099e450c8eebbc3318f827a8532448f6a8631f Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Thu, 18 Apr 2013 17:09:40 +0100 +Subject: [PATCH 03/28] url: Re-factored set_userpass() and + parse_url_userpass() + +Re-factored these functions to reflect their new behaviour following the +addition of login options. + +Upstream-commit: 0d49e408a48246b9a27448473e78ce3fd237b19e +Signed-off-by: Kamil Dudka +--- + lib/url.c | 41 +++++++++++++++++++++++------------------ + 1 file changed, 23 insertions(+), 18 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 4a9df84..f03ca0f 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -138,9 +138,9 @@ find_oldest_idle_connection(struct SessionHandle *data); + static void conn_free(struct connectdata *conn); + static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke); + static CURLcode do_init(struct connectdata *conn); +-static CURLcode parse_url_userpass(struct SessionHandle *data, +- struct connectdata *conn, +- char *user, char *passwd, char *options); ++static CURLcode parse_url_login(struct SessionHandle *data, ++ struct connectdata *conn, ++ char *user, char *passwd, char *options); + /* + * Protocol table. + */ +@@ -3806,11 +3806,11 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data, + data->change.url_alloc = TRUE; /* free this later */ + } + +- /************************************************************* +- * Parse a user name and password in the URL and strip it out +- * of the host name +- *************************************************************/ +- result = parse_url_userpass(data, conn, user, passwd, options); ++ /* ++ * Parse the login details from the URL and strip them out of ++ * the host name ++ */ ++ result = parse_url_login(data, conn, user, passwd, options); + if(result != CURLE_OK) + return result; + +@@ -4268,7 +4268,8 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data, + + /* + * +- * Parse a user name and password in the URL and strip it out of the host name ++ * Parse the login details (user name, password and options) from the URL and ++ * strip them out of the host name + * + * Inputs: data->set.use_netrc (CURLOPT_NETRC) + * conn->host.name +@@ -4276,12 +4277,13 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data, + * Outputs: (almost :- all currently undefined) + * conn->bits.user_passwd - non-zero if non-default passwords exist + * user - non-zero length if defined +- * passwd - ditto ++ * passwd - non-zero length if defined ++ * options - non-zero length if defined + * conn->host.name - remove user name and password + */ +-static CURLcode parse_url_userpass(struct SessionHandle *data, +- struct connectdata *conn, +- char *user, char *passwd, char *options) ++static CURLcode parse_url_login(struct SessionHandle *data, ++ struct connectdata *conn, ++ char *user, char *passwd, char *options) + { + /* At this point, we're hoping all the other special cases have + * been taken care of, so conn->host.name is at most +@@ -4547,20 +4549,23 @@ static void override_userpass(struct SessionHandle *data, + /* + * Set password so it's available in the connection. + */ +-static CURLcode set_userpass(struct connectdata *conn, +- const char *user, const char *passwd, +- const char *options) ++static CURLcode set_login(struct connectdata *conn, ++ const char *user, const char *passwd, ++ const char *options) + { + CURLcode result = CURLE_OK; + + /* If our protocol needs a password and we have none, use the defaults */ + if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) { +- ++ /* Store the default user */ + conn->user = strdup(CURL_DEFAULT_USER); ++ ++ /* Store the default password */ + if(conn->user) + conn->passwd = strdup(CURL_DEFAULT_PASSWORD); + else + conn->passwd = NULL; ++ + /* This is the default password, so DON'T set conn->bits.user_passwd */ + } + else { +@@ -5028,7 +5033,7 @@ static CURLcode create_conn(struct SessionHandle *data, + * for use + *************************************************************/ + override_userpass(data, conn, user, passwd); +- result = set_userpass(conn, user, passwd, options); ++ result = set_login(conn, user, passwd, options); + if(result != CURLE_OK) + return result; + +-- +2.4.6 + + +From a66a0feefcb037ffcfaf2dbd3dcd9f17a416ad13 Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Thu, 18 Apr 2013 17:52:05 +0100 +Subject: [PATCH 04/28] url: Moved parsing of login details out of + parse_url_login() + +Separated the parsing of login details from the processing of them in +parse_url_login() ready for use by setstropt_userpwd(). + +Upstream-commit: bb20989a6384f95a73fd68b0e109fc860e0c7a57 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 221 +++++++++++++++++++++++++++++++++++++++++++++----------------- + 1 file changed, 161 insertions(+), 60 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index f03ca0f..3396944 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -141,6 +141,9 @@ static CURLcode do_init(struct connectdata *conn); + static CURLcode parse_url_login(struct SessionHandle *data, + struct connectdata *conn, + char *user, char *passwd, char *options); ++static CURLcode parse_login_details(const char *login, const size_t len, ++ char **userptr, char **passwdptr, ++ char **optionsptr); + /* + * Protocol table. + */ +@@ -4267,6 +4270,7 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data, + #endif /* CURL_DISABLE_PROXY */ + + /* ++ * parse_url_login() + * + * Parse the login details (user name, password and options) from the URL and + * strip them out of the host name +@@ -4285,6 +4289,11 @@ static CURLcode parse_url_login(struct SessionHandle *data, + struct connectdata *conn, + char *user, char *passwd, char *options) + { ++ CURLcode result = CURLE_OK; ++ char *userp = NULL; ++ char *passwdp = NULL; ++ char *optionsp = NULL; ++ + /* At this point, we're hoping all the other special cases have + * been taken care of, so conn->host.name is at most + * [user[:password][;options]]@]hostname +@@ -4293,7 +4302,7 @@ static CURLcode parse_url_login(struct SessionHandle *data, + */ + + char *ptr = strchr(conn->host.name, '@'); +- char *userpass = conn->host.name; ++ char *login = conn->host.name; + + user[0] = 0; /* to make everything well-defined */ + passwd[0] = 0; +@@ -4302,7 +4311,7 @@ static CURLcode parse_url_login(struct SessionHandle *data, + /* We will now try to extract the + * possible login information in a string like: + * ftp://user:password@ftp.my.site:8021/README */ +- if(ptr != NULL) { ++ if(ptr) { + /* There's login information to the left of the @ */ + + conn->host.name = ++ptr; +@@ -4314,80 +4323,172 @@ static CURLcode parse_url_login(struct SessionHandle *data, + */ + + if(data->set.use_netrc != CURL_NETRC_REQUIRED) { +- /* We could use the information in the URL so extract it */ +- if(*userpass != ':') { +- if(*userpass != ';') { +- /* The user is given so extract the user, password and options */ +- int result = sscanf(userpass, +- "%" MAX_CURL_USER_LENGTH_TXT "[^:;@]:" +- "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^;@];" +- "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", +- user, passwd, options); +- +- /* The extract failed so extract the user and options instead */ +- if(result == 1) +- sscanf(userpass, "%" MAX_CURL_USER_LENGTH_TXT "[^:;@];" +- "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", +- user, options); +- } +- else { +- /* No name or password are given so extract the options only */ +- sscanf(userpass, ";%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", options); ++ /* We could use the login information in the URL so extract it */ ++ result = parse_login_details(login, ptr - login - 1, ++ &userp, &passwdp, &optionsp); ++ if(!result) { ++ if(userp) { ++ char *newname; ++ ++ /* We have a user in the URL */ ++ conn->bits.userpwd_in_url = TRUE; ++ conn->bits.user_passwd = TRUE; /* enable user+password */ ++ ++ /* Decode the user */ ++ newname = curl_easy_unescape(data, userp, 0, NULL); ++ if(!newname) ++ return CURLE_OUT_OF_MEMORY; ++ ++ if(strlen(newname) < MAX_CURL_USER_LENGTH) ++ strcpy(user, newname); ++ ++ free(newname); + } +- } +- else +- /* No name is given so extract the password and options */ +- sscanf(userpass, ":%" MAX_CURL_PASSWORD_LENGTH_TXT "[^;@];" +- "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", +- passwd, options); + +- if(user[0]) { +- char *newname; ++ if(passwdp) { ++ /* We have a password in the URL so decode it */ ++ char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL); ++ if(!newpasswd) ++ return CURLE_OUT_OF_MEMORY; + +- /* We have a user in the URL */ +- conn->bits.userpwd_in_url = TRUE; +- conn->bits.user_passwd = TRUE; /* enable user+password */ ++ if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH) ++ strcpy(passwd, newpasswd); + +- /* Decode the user */ +- newname = curl_easy_unescape(data, user, 0, NULL); +- if(!newname) +- return CURLE_OUT_OF_MEMORY; ++ free(newpasswd); ++ } ++ ++ if(optionsp) { ++ /* We have an options list in the URL so decode it */ ++ char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL); ++ if(!newoptions) ++ return CURLE_OUT_OF_MEMORY; + +- if(strlen(newname) < MAX_CURL_USER_LENGTH) +- strcpy(user, newname); ++ if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH) ++ strcpy(options, newoptions); + +- /* if the new name is longer than accepted, then just use +- the unconverted name, it'll be wrong but what the heck */ +- free(newname); ++ free(newoptions); ++ } + } + +- if(passwd[0]) { +- /* We have a password in the URL so decode it */ +- char *newpasswd = curl_easy_unescape(data, passwd, 0, NULL); +- if(!newpasswd) +- return CURLE_OUT_OF_MEMORY; ++ Curl_safefree(userp); ++ Curl_safefree(passwdp); ++ Curl_safefree(optionsp); ++ } ++ } + +- if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH) +- strcpy(passwd, newpasswd); ++ return result; ++} + +- free(newpasswd); +- } ++/* ++ * parse_login_details() ++ * ++ * This is used to parse a login string for user name, password and options in ++ * the following formats: ++ * ++ * user ++ * user:password ++ * user:password;options ++ * user;options ++ * user;options:password ++ * :password ++ * :password;options ++ * ;options ++ * ;options:password ++ * ++ * Parameters: ++ * ++ * login [in] - The login string. ++ * len [in] - The length of the login string. ++ * userp [in/out] - The address where a pointer to newly allocated memory ++ * holding the user will be stored upon completion. ++ * passdwp [in/out] - The address where a pointer to newly allocated memory ++ * holding the password will be stored upon completion. ++ * optionsp [in/out] - The address where a pointer to newly allocated memory ++ * holding the options will be stored upon completion. ++ * ++ * Returns CURLE_OK on success. ++ */ ++static CURLcode parse_login_details(const char *login, const size_t len, ++ char **userp, char **passwdp, ++ char **optionsp) ++{ ++ CURLcode result = CURLE_OK; ++ char *utemp = NULL; ++ char *ptemp = NULL; ++ char *otemp = NULL; ++ const char *psep = NULL; ++ const char *osep = NULL; ++ size_t ulen; ++ size_t plen; ++ size_t olen; ++ ++ /* Attempt to find the password separator */ ++ if(passwdp) ++ psep = strchr(login, ':'); ++ ++ /* Attempt to find the options separator */ ++ if(optionsp) ++ osep = strchr(login, ';'); ++ ++ /* Calculate the portion lengths */ ++ ulen = (psep ? ++ (size_t)(osep && psep > osep ? osep - login : psep - login) : ++ (osep ? (size_t)(osep - login) : len)); ++ plen = (psep ? ++ (osep && osep > psep ? (size_t)(osep - psep) : ++ (size_t)(login + len - psep)) - 1 : 0); ++ olen = (osep ? ++ (psep && psep > osep ? (size_t)(psep - osep) : ++ (size_t)(login + len - osep)) - 1 : 0); ++ ++ /* Allocate the user portion temporary buffer */ ++ if(userp && ulen) { ++ utemp = malloc(ulen + 1); ++ if(!utemp) ++ result = CURLE_OUT_OF_MEMORY; ++ } ++ ++ /* Allocate the password portion temporary buffer */ ++ if(!result && passwdp && plen) { ++ ptemp = malloc(plen + 1); ++ if(!ptemp) ++ result = CURLE_OUT_OF_MEMORY; ++ } ++ ++ /* Allocate the options portion temporary buffer */ ++ if(!result && optionsp && olen) { ++ otemp = malloc(olen + 1); ++ if(!otemp) ++ result = CURLE_OUT_OF_MEMORY; ++ } + +- if(options[0]) { +- /* We have an options list in the URL so decode it */ +- char *newoptions = curl_easy_unescape(data, options, 0, NULL); +- if(!newoptions) +- return CURLE_OUT_OF_MEMORY; ++ if(!result) { ++ /* Copy the user portion if necessary */ ++ if(utemp) { ++ memcpy(utemp, login, ulen); ++ utemp[ulen] = '\0'; ++ Curl_safefree(*userp); ++ *userp = utemp; ++ } + +- if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH) +- strcpy(options, newoptions); ++ /* Copy the password portion if necessary */ ++ if(ptemp) { ++ memcpy(ptemp, psep + 1, plen); ++ ptemp[plen] = '\0'; ++ Curl_safefree(*passwdp); ++ *passwdp = ptemp; ++ } + +- free(newoptions); +- } ++ /* Copy the options portion if necessary */ ++ if(otemp) { ++ memcpy(otemp, osep + 1, olen); ++ otemp[olen] = '\0'; ++ Curl_safefree(*optionsp); ++ *optionsp = otemp; + } + } + +- return CURLE_OK; ++ return result; + } + + /************************************************************* +-- +2.4.6 + + +From ce1718fc19267ca33e61ac4bff2e3867d6ed460c Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Fri, 19 Apr 2013 19:37:55 +0100 +Subject: [PATCH 05/28] url: Added bounds checking to parse_login_details() + +Added bounds checking when searching for the separator characters within +the login string as this string may not be NULL terminated (For example +it is the login part of a URL). We do this in preference to allocating a +new string to copy the login details into which could then be passed to +parse_login_details() for performance reasons. + +Upstream-commit: 49184c37233c2cf27b79ebcd29fb8a4f5fb2e1ed +Signed-off-by: Kamil Dudka +--- + lib/url.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 3396944..5381872 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4423,13 +4423,23 @@ static CURLcode parse_login_details(const char *login, const size_t len, + size_t olen; + + /* Attempt to find the password separator */ +- if(passwdp) ++ if(passwdp) { + psep = strchr(login, ':'); + ++ /* Within the constraint of the login string */ ++ if(psep >= login + len) ++ psep = NULL; ++ } ++ + /* Attempt to find the options separator */ +- if(optionsp) ++ if(optionsp) { + osep = strchr(login, ';'); + ++ /* Within the constraint of the login string */ ++ if(osep >= login + len) ++ osep = NULL; ++ } ++ + /* Calculate the portion lengths */ + ulen = (psep ? + (size_t)(osep && psep > osep ? osep - login : psep - login) : +-- +2.4.6 + + +From fb76a0dac86f2b82f68b6b3b7538b5057d1c04d9 Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sat, 20 Apr 2013 08:47:59 +0100 +Subject: [PATCH 06/28] url: Added support for parsing login options from the + CURLOPT_USERPWD + +In addition to parsing the optional login options from the URL, added +support for parsing them from CURLOPT_USERPWD, to allow the following +supported command line: + +--user username:password;options + +Upstream-commit: fddb7b44a79d78e05043e1c97e069308b6b85f79 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 66 ++++++++++++++++++++++++++++++++++------------------------- + lib/urldata.h | 1 + + 2 files changed, 39 insertions(+), 28 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 5381872..0a47143 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -295,43 +295,52 @@ static CURLcode setstropt(char **charp, char * s) + } + + static CURLcode setstropt_userpwd(char *option, char **user_storage, +- char **pwd_storage) ++ char **pwd_storage, char **options_storage) + { +- char* separator; + CURLcode result = CURLE_OK; ++ char *userp = NULL; ++ char *passwdp = NULL; ++ char *optionsp = NULL; + + if(!option) { + /* we treat a NULL passed in as a hint to clear existing info */ +- Curl_safefree(*user_storage); +- *user_storage = (char *) NULL; +- Curl_safefree(*pwd_storage); +- *pwd_storage = (char *) NULL; ++ if(user_storage) { ++ Curl_safefree(*user_storage); ++ *user_storage = (char *) NULL; ++ } ++ ++ if(pwd_storage) { ++ Curl_safefree(*pwd_storage); ++ *pwd_storage = (char *) NULL; ++ } ++ ++ if(options_storage) { ++ Curl_safefree(*options_storage); ++ *options_storage = (char *) NULL; ++ } ++ + return CURLE_OK; + } + +- separator = strchr(option, ':'); +- if(separator != NULL) { +- ++ /* Parse the login details */ ++ result = parse_login_details(option, strlen(option), ++ (user_storage ? &userp : NULL), ++ (pwd_storage ? &passwdp : NULL), ++ (options_storage ? &optionsp : NULL)); ++ if(!result) { + /* store username part of option */ +- char * p; +- size_t username_len = (size_t)(separator-option); +- p = malloc(username_len+1); +- if(!p) +- result = CURLE_OUT_OF_MEMORY; +- else { +- memcpy(p, option, username_len); +- p[username_len] = '\0'; +- Curl_safefree(*user_storage); +- *user_storage = p; +- } ++ if(user_storage) ++ setstropt(user_storage, userp); + + /* store password part of option */ +- if(result == CURLE_OK) +- result = setstropt(pwd_storage, separator+1); +- } +- else { +- result = setstropt(user_storage, option); ++ if(pwd_storage) ++ setstropt(pwd_storage, passwdp); ++ ++ /* store options part of option */ ++ if(options_storage) ++ setstropt(options_storage, optionsp); + } ++ + return result; + } + +@@ -1546,11 +1555,12 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, + + case CURLOPT_USERPWD: + /* +- * user:password to use in the operation ++ * user:password;options to use in the operation + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_USERNAME], +- &data->set.str[STRING_PASSWORD]); ++ &data->set.str[STRING_PASSWORD], ++ &data->set.str[STRING_OPTIONS]); + break; + case CURLOPT_USERNAME: + /* +@@ -1623,7 +1633,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_PROXYUSERNAME], +- &data->set.str[STRING_PROXYPASSWORD]); ++ &data->set.str[STRING_PROXYPASSWORD], NULL); + break; + case CURLOPT_PROXYUSERNAME: + /* +diff --git a/lib/urldata.h b/lib/urldata.h +index 46ef5d5..1c2281a 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1354,6 +1354,7 @@ enum dupstring { + STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */ + STRING_USERNAME, /* , if used */ + STRING_PASSWORD, /* , if used */ ++ STRING_OPTIONS, /* , if used */ + STRING_PROXYUSERNAME, /* Proxy , if used */ + STRING_PROXYPASSWORD, /* Proxy , if used */ + STRING_NOPROXY, /* List of hosts which should not use the proxy, if +-- +2.4.6 + + +From 32f237261f2c7592db3ba6378c053e63abb744ce Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sat, 20 Apr 2013 09:06:53 +0100 +Subject: [PATCH 07/28] url: Added overriding of URL login options from + CURLOPT_USERPWD + +Upstream-commit: d535c4a2e1f78d4b54767d67e17cca805e2d1f7c +Signed-off-by: Kamil Dudka +--- + lib/url.c | 31 +++++++++++++++++-------------- + 1 file changed, 17 insertions(+), 14 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 0a47143..8b7aa3a 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4631,20 +4631,26 @@ static CURLcode parse_remote_port(struct SessionHandle *data, + } + + /* +- * Override a user name and password from the URL with that in the +- * CURLOPT_USERPWD option or a .netrc file, if applicable. ++ * Override the login details from the URL with that in the CURLOPT_USERPWD ++ * option or a .netrc file, if applicable. + */ +-static void override_userpass(struct SessionHandle *data, +- struct connectdata *conn, +- char *user, char *passwd) ++static void override_login(struct SessionHandle *data, ++ struct connectdata *conn, ++ char *user, char *passwd, char *options) + { +- if(data->set.str[STRING_USERNAME] != NULL) { ++ if(data->set.str[STRING_USERNAME]) { + strncpy(user, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH); +- user[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/ ++ user[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */ + } +- if(data->set.str[STRING_PASSWORD] != NULL) { ++ ++ if(data->set.str[STRING_PASSWORD]) { + strncpy(passwd, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH); +- passwd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/ ++ passwd[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */ ++ } ++ ++ if(data->set.str[STRING_OPTIONS]) { ++ strncpy(options, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH); ++ options[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */ + } + + conn->bits.netrc = FALSE; +@@ -5149,11 +5155,8 @@ static CURLcode create_conn(struct SessionHandle *data, + if(result != CURLE_OK) + return result; + +- /************************************************************* +- * Check for an overridden user name and password, then set it +- * for use +- *************************************************************/ +- override_userpass(data, conn, user, passwd); ++ /* Check for overridden login details and set them accordingly */ ++ override_login(data, conn, user, passwd, options); + result = set_login(conn, user, passwd, options); + if(result != CURLE_OK) + return result; +-- +2.4.6 + + +From 4876aa898d1d0b012328c3ddc96fd2023464584e Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sat, 20 Apr 2013 18:40:13 +0100 +Subject: [PATCH 08/28] url: Fixed memory leak in setstropt_userpwd() + +setstropt_userpwd() was calling setstropt() in commit fddb7b44a79d to +set each of the login details which would duplicate the strings and +subsequently cause a memory leak. + +Upstream-commit: fe880475ed3c7e51e32e19112252c79e921cc31b +Signed-off-by: Kamil Dudka +--- + lib/url.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 8b7aa3a..5e27818 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -330,15 +330,18 @@ static CURLcode setstropt_userpwd(char *option, char **user_storage, + if(!result) { + /* store username part of option */ + if(user_storage) +- setstropt(user_storage, userp); ++ Curl_safefree(*user_storage); ++ *user_storage = userp; + + /* store password part of option */ + if(pwd_storage) +- setstropt(pwd_storage, passwdp); ++ Curl_safefree(*pwd_storage); ++ *pwd_storage = passwdp; + + /* store options part of option */ + if(options_storage) +- setstropt(options_storage, optionsp); ++ Curl_safefree(*options_storage); ++ *options_storage = optionsp; + } + + return result; +-- +2.4.6 + + +From d0d89877466515b3ec17bc7c5987f4fec906e92e Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sat, 20 Apr 2013 19:10:10 +0100 +Subject: [PATCH 09/28] url: Correction to scope of if statements when setting + data + +Upstream-commit: e99c81a07c0c8752a286e0f14174ae7ae114090c +Signed-off-by: Kamil Dudka +--- + lib/url.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 5e27818..ffd80a5 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -329,19 +329,22 @@ static CURLcode setstropt_userpwd(char *option, char **user_storage, + (options_storage ? &optionsp : NULL)); + if(!result) { + /* store username part of option */ +- if(user_storage) ++ if(user_storage) { + Curl_safefree(*user_storage); + *user_storage = userp; ++ } + + /* store password part of option */ +- if(pwd_storage) ++ if(pwd_storage) { + Curl_safefree(*pwd_storage); + *pwd_storage = passwdp; ++ } + + /* store options part of option */ +- if(options_storage) ++ if(options_storage) { + Curl_safefree(*options_storage); + *options_storage = optionsp; ++ } + } + + return result; +-- +2.4.6 + + +From f45b4761cdb3b88647aa4b7eee89bb45dfd7c7bc Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sat, 20 Apr 2013 20:01:40 +0100 +Subject: [PATCH 10/28] url: Simplified setstropt_userpwd() following recent + changes + +There is no need to perform separate clearing of data if a NULL option +pointer is passed in. Instead this operation can be performed by simply +not calling parse_login_details() and letting the rest of the code do +the work. + +Upstream-commit: bddf3d4705ed8e0999200c92de191db8e2441b3a +Signed-off-by: Kamil Dudka +--- + lib/url.c | 30 +++++++----------------------- + 1 file changed, 7 insertions(+), 23 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index ffd80a5..5f1bef2 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -302,31 +302,15 @@ static CURLcode setstropt_userpwd(char *option, char **user_storage, + char *passwdp = NULL; + char *optionsp = NULL; + +- if(!option) { +- /* we treat a NULL passed in as a hint to clear existing info */ +- if(user_storage) { +- Curl_safefree(*user_storage); +- *user_storage = (char *) NULL; +- } +- +- if(pwd_storage) { +- Curl_safefree(*pwd_storage); +- *pwd_storage = (char *) NULL; +- } +- +- if(options_storage) { +- Curl_safefree(*options_storage); +- *options_storage = (char *) NULL; +- } +- +- return CURLE_OK; ++ /* Parse the login details if specified. It not then we treat NULL as a hint ++ to clear the existing data */ ++ if(option) { ++ result = parse_login_details(option, strlen(option), ++ (user_storage ? &userp : NULL), ++ (pwd_storage ? &passwdp : NULL), ++ (options_storage ? &optionsp : NULL)); + } + +- /* Parse the login details */ +- result = parse_login_details(option, strlen(option), +- (user_storage ? &userp : NULL), +- (pwd_storage ? &passwdp : NULL), +- (options_storage ? &optionsp : NULL)); + if(!result) { + /* store username part of option */ + if(user_storage) { +-- +2.4.6 + + +From 34d2d13cdc6a50ea80c45366ea78487cca8f0fc4 Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sun, 21 Apr 2013 10:08:17 +0100 +Subject: [PATCH 11/28] url: Tidy up of code and comments following recent + changes + +Tidy up of variable names and comments in setstropt_userpwd() and +parse_login_details(). + +Upstream-commit: e8a9f794f048251f94d59cc1d4ef7e9516b0c4e7 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 84 +++++++++++++++++++++++++++++++-------------------------------- + 1 file changed, 42 insertions(+), 42 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 5f1bef2..5f9fd6f 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -261,7 +261,7 @@ static const struct Curl_handler Curl_handler_dummy = { + PROTOPT_NONE /* flags */ + }; + +-void Curl_freeset(struct SessionHandle * data) ++void Curl_freeset(struct SessionHandle *data) + { + /* Free all dynamic strings stored in the data->set substructure. */ + enum dupstring i; +@@ -275,7 +275,7 @@ void Curl_freeset(struct SessionHandle * data) + data->change.referer = NULL; + } + +-static CURLcode setstropt(char **charp, char * s) ++static CURLcode setstropt(char **charp, char *s) + { + /* Release the previous storage at `charp' and replace by a dynamic storage + copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */ +@@ -298,43 +298,43 @@ static CURLcode setstropt_userpwd(char *option, char **user_storage, + char **pwd_storage, char **options_storage) + { + CURLcode result = CURLE_OK; +- char *userp = NULL; +- char *passwdp = NULL; +- char *optionsp = NULL; ++ char *user = NULL; ++ char *passwd = NULL; ++ char *options = NULL; + + /* Parse the login details if specified. It not then we treat NULL as a hint + to clear the existing data */ + if(option) { + result = parse_login_details(option, strlen(option), +- (user_storage ? &userp : NULL), +- (pwd_storage ? &passwdp : NULL), +- (options_storage ? &optionsp : NULL)); ++ (user_storage ? &user : NULL), ++ (pwd_storage ? &passwd : NULL), ++ (options_storage ? &options : NULL)); + } + + if(!result) { +- /* store username part of option */ ++ /* Store the username part of option if required */ + if(user_storage) { + Curl_safefree(*user_storage); +- *user_storage = userp; ++ *user_storage = user; + } + +- /* store password part of option */ ++ /* Store the password part of option if required */ + if(pwd_storage) { + Curl_safefree(*pwd_storage); +- *pwd_storage = passwdp; ++ *pwd_storage = passwd; + } + +- /* store options part of option */ ++ /* Store the options part of option if required */ + if(options_storage) { + Curl_safefree(*options_storage); +- *options_storage = optionsp; ++ *options_storage = options; + } + } + + return result; + } + +-CURLcode Curl_dupset(struct SessionHandle * dst, struct SessionHandle * src) ++CURLcode Curl_dupset(struct SessionHandle *dst, struct SessionHandle *src) + { + CURLcode r = CURLE_OK; + enum dupstring i; +@@ -4413,9 +4413,9 @@ static CURLcode parse_login_details(const char *login, const size_t len, + char **optionsp) + { + CURLcode result = CURLE_OK; +- char *utemp = NULL; +- char *ptemp = NULL; +- char *otemp = NULL; ++ char *ubuf = NULL; ++ char *pbuf = NULL; ++ char *obuf = NULL; + const char *psep = NULL; + const char *osep = NULL; + size_t ulen; +@@ -4451,50 +4451,50 @@ static CURLcode parse_login_details(const char *login, const size_t len, + (psep && psep > osep ? (size_t)(psep - osep) : + (size_t)(login + len - osep)) - 1 : 0); + +- /* Allocate the user portion temporary buffer */ ++ /* Allocate the user portion buffer */ + if(userp && ulen) { +- utemp = malloc(ulen + 1); +- if(!utemp) ++ ubuf = malloc(ulen + 1); ++ if(!ubuf) + result = CURLE_OUT_OF_MEMORY; + } + +- /* Allocate the password portion temporary buffer */ ++ /* Allocate the password portion buffer */ + if(!result && passwdp && plen) { +- ptemp = malloc(plen + 1); +- if(!ptemp) ++ pbuf = malloc(plen + 1); ++ if(!pbuf) + result = CURLE_OUT_OF_MEMORY; + } + +- /* Allocate the options portion temporary buffer */ ++ /* Allocate the options portion buffer */ + if(!result && optionsp && olen) { +- otemp = malloc(olen + 1); +- if(!otemp) ++ obuf = malloc(olen + 1); ++ if(!obuf) + result = CURLE_OUT_OF_MEMORY; + } + + if(!result) { +- /* Copy the user portion if necessary */ +- if(utemp) { +- memcpy(utemp, login, ulen); +- utemp[ulen] = '\0'; ++ /* Store the user portion if necessary */ ++ if(ubuf) { ++ memcpy(ubuf, login, ulen); ++ ubuf[ulen] = '\0'; + Curl_safefree(*userp); +- *userp = utemp; ++ *userp = ubuf; + } + +- /* Copy the password portion if necessary */ +- if(ptemp) { +- memcpy(ptemp, psep + 1, plen); +- ptemp[plen] = '\0'; ++ /* Store the password portion if necessary */ ++ if(pbuf) { ++ memcpy(pbuf, psep + 1, plen); ++ pbuf[plen] = '\0'; + Curl_safefree(*passwdp); +- *passwdp = ptemp; ++ *passwdp = pbuf; + } + +- /* Copy the options portion if necessary */ +- if(otemp) { +- memcpy(otemp, osep + 1, olen); +- otemp[olen] = '\0'; ++ /* Store the options portion if necessary */ ++ if(obuf) { ++ memcpy(obuf, osep + 1, olen); ++ obuf[olen] = '\0'; + Curl_safefree(*optionsp); +- *optionsp = otemp; ++ *optionsp = obuf; + } + } + +-- +2.4.6 + + +From 58e3995c51150621185e9e0ebcbd943403a2df9c Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sun, 21 Apr 2013 10:16:51 +0100 +Subject: [PATCH 12/28] url: Tidy up of setstropt_userpwd() parameters + +Updated the naming convention of the login parameters to match those of +other functions. + +Upstream-commit: 702b0dd408d5e847aad99d44dcd79366c61835eb +Signed-off-by: Kamil Dudka +--- + lib/url.c | 28 ++++++++++++++-------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 5f9fd6f..2e691c3 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -294,8 +294,8 @@ static CURLcode setstropt(char **charp, char *s) + return CURLE_OK; + } + +-static CURLcode setstropt_userpwd(char *option, char **user_storage, +- char **pwd_storage, char **options_storage) ++static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp, ++ char **optionsp) + { + CURLcode result = CURLE_OK; + char *user = NULL; +@@ -306,28 +306,28 @@ static CURLcode setstropt_userpwd(char *option, char **user_storage, + to clear the existing data */ + if(option) { + result = parse_login_details(option, strlen(option), +- (user_storage ? &user : NULL), +- (pwd_storage ? &passwd : NULL), +- (options_storage ? &options : NULL)); ++ (userp ? &user : NULL), ++ (passwdp ? &passwd : NULL), ++ (optionsp ? &options : NULL)); + } + + if(!result) { + /* Store the username part of option if required */ +- if(user_storage) { +- Curl_safefree(*user_storage); +- *user_storage = user; ++ if(userp) { ++ Curl_safefree(*userp); ++ *userp = user; + } + + /* Store the password part of option if required */ +- if(pwd_storage) { +- Curl_safefree(*pwd_storage); +- *pwd_storage = passwd; ++ if(passwdp) { ++ Curl_safefree(*passwdp); ++ *passwdp = passwd; + } + + /* Store the options part of option if required */ +- if(options_storage) { +- Curl_safefree(*options_storage); +- *options_storage = options; ++ if(optionsp) { ++ Curl_safefree(*optionsp); ++ *optionsp = options; + } + } + +-- +2.4.6 + + +From 956dfd17565bb95ebf8cd7f7a2fe5a76e7da1898 Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sun, 21 Apr 2013 12:08:35 +0100 +Subject: [PATCH 13/28] url: Updated proxy URL parsing to use + parse_login_details() + +Upstream-commit: 11332577b3cbd76f9fc418f3ae11133e4089fa1c +Signed-off-by: Kamil Dudka +--- + lib/url.c | 26 +++++++++++++------------- + 1 file changed, 13 insertions(+), 13 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 2e691c3..a272087 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4137,16 +4137,13 @@ static CURLcode parse_proxy(struct SessionHandle *data, + /* Is there a username and password given in this proxy url? */ + atsign = strchr(proxyptr, '@'); + if(atsign) { +- char proxyuser[MAX_CURL_USER_LENGTH]; +- char proxypasswd[MAX_CURL_PASSWORD_LENGTH]; +- proxypasswd[0] = 0; +- +- if(1 <= sscanf(proxyptr, +- "%" MAX_CURL_USER_LENGTH_TXT"[^:@]:" +- "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^@]", +- proxyuser, proxypasswd)) { +- CURLcode res = CURLE_OK; ++ CURLcode res = CURLE_OK; ++ char *proxyuser = NULL; ++ char *proxypasswd = NULL; + ++ res = parse_login_details(proxyptr, atsign - proxyptr, ++ &proxyuser, &proxypasswd, NULL); ++ if(!res) { + /* found user and password, rip them out. note that we are + unescaping them, as there is otherwise no way to have a + username or password with reserved characters like ':' in +@@ -4164,7 +4161,7 @@ static CURLcode parse_proxy(struct SessionHandle *data, + res = CURLE_OUT_OF_MEMORY; + } + +- if(CURLE_OK == res) { ++ if(!res) { + conn->bits.proxy_user_passwd = TRUE; /* enable it */ + atsign++; /* the right side of the @-letter */ + +@@ -4173,10 +4170,13 @@ static CURLcode parse_proxy(struct SessionHandle *data, + else + res = CURLE_OUT_OF_MEMORY; + } +- +- if(res) +- return res; + } ++ ++ Curl_safefree(proxyuser); ++ Curl_safefree(proxypasswd); ++ ++ if(res) ++ return res; + } + + /* start scanning for port number at this point */ +-- +2.4.6 + + +From e2480db78651e3d1e2f5939d09b7ada54af0bdf4 Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sun, 21 Apr 2013 16:55:19 +0100 +Subject: [PATCH 14/28] url: Fixed crash when no username or password supplied + for proxy + +Fixed an issue in parse_proxy(), introduced in commit 11332577b3cb, +where an empty username or password (For example: http://:@example.com) +would cause a crash. + +Upstream-commit: 416ecc15845c4e6bf7ea6359d9c63adec3385f5b +Signed-off-by: Kamil Dudka +--- + lib/url.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index a272087..736f4d9 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4149,13 +4149,19 @@ static CURLcode parse_proxy(struct SessionHandle *data, + username or password with reserved characters like ':' in + them. */ + Curl_safefree(conn->proxyuser); +- conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL); ++ if(proxyuser) ++ conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL); ++ else ++ conn->proxyuser = strdup(""); + + if(!conn->proxyuser) + res = CURLE_OUT_OF_MEMORY; + else { + Curl_safefree(conn->proxypasswd); +- conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL); ++ if(proxypasswd) ++ conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL); ++ else ++ conn->proxypasswd = strdup(""); + + if(!conn->proxypasswd) + res = CURLE_OUT_OF_MEMORY; +-- +2.4.6 + + +From c77ec0c919be4f86cd5fb70fa6813b28b376f48e Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sun, 21 Apr 2013 18:29:33 +0100 +Subject: [PATCH 15/28] url: Fixed missing length check in parse_proxy() + +Commit 11332577b3cb removed the length check that was performed by the +old scanf() code. + +Upstream-commit: ddac43b38e3fd923b71554126652b05e034d6900 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 736f4d9..ede7d1c 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4149,7 +4149,7 @@ static CURLcode parse_proxy(struct SessionHandle *data, + username or password with reserved characters like ':' in + them. */ + Curl_safefree(conn->proxyuser); +- if(proxyuser) ++ if(proxyuser && strlen(proxyuser) < MAX_CURL_USER_LENGTH) + conn->proxyuser = curl_easy_unescape(data, proxyuser, 0, NULL); + else + conn->proxyuser = strdup(""); +@@ -4158,7 +4158,7 @@ static CURLcode parse_proxy(struct SessionHandle *data, + res = CURLE_OUT_OF_MEMORY; + else { + Curl_safefree(conn->proxypasswd); +- if(proxypasswd) ++ if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH) + conn->proxypasswd = curl_easy_unescape(data, proxypasswd, 0, NULL); + else + conn->proxypasswd = strdup(""); +-- +2.4.6 + + +From 4d396dba81cde42581a313a2dbe983a1d985045a Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Sun, 30 Jun 2013 19:51:16 +0200 +Subject: [PATCH 16/28] url: restore the functionality of 'curl -u :' + +This commit fixes a regression introduced in +fddb7b44a79d78e05043e1c97e069308b6b85f79. + +Reported by: Markus Moeller +Bug: http://curl.haxx.se/mail/archive-2013-06/0052.html + +Upstream-commit: abca89aaa0fb208cfaf4ead6692014c4e553388a +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 ede7d1c..a2b9abb 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -314,6 +314,13 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp, + if(!result) { + /* Store the username part of option if required */ + if(userp) { ++ if(!user && option && option[0] == ':') { ++ /* Allocate an empty string instead of returning NULL as user name */ ++ user = strdup(""); ++ if(!user) ++ result = CURLE_OUT_OF_MEMORY; ++ } ++ + Curl_safefree(*userp); + *userp = user; + } +-- +2.4.6 + + +From 0df43fcefa7ba9f47e509b4a55edd6b287dd962e Mon Sep 17 00:00:00 2001 +From: Yang Tse +Date: Fri, 12 Jul 2013 12:16:48 +0200 +Subject: [PATCH 17/28] url.c: fix parse_login_details() OOM handling + +Upstream-commit: 83f0dae1292b8b9b2507457db6b3ab22ba31c64b +Signed-off-by: Kamil Dudka +--- + lib/url.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index a2b9abb..61ca8e8 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4474,15 +4474,20 @@ static CURLcode parse_login_details(const char *login, const size_t len, + /* Allocate the password portion buffer */ + if(!result && passwdp && plen) { + pbuf = malloc(plen + 1); +- if(!pbuf) ++ if(!pbuf) { ++ Curl_safefree(ubuf); + result = CURLE_OUT_OF_MEMORY; ++ } + } + + /* Allocate the options portion buffer */ + if(!result && optionsp && olen) { + obuf = malloc(olen + 1); +- if(!obuf) ++ if(!obuf) { ++ Curl_safefree(pbuf); ++ Curl_safefree(ubuf); + result = CURLE_OUT_OF_MEMORY; ++ } + } + + if(!result) { +-- +2.4.6 + + +From 386bc0349e102cbe9a0417688e15ea7e13cf4dd8 Mon Sep 17 00:00:00 2001 +From: Yang Tse +Date: Sun, 14 Jul 2013 12:19:57 +0200 +Subject: [PATCH 18/28] url.c: fix parse_url_login() OOM handling + +Upstream-commit: cfc907e43d5f25a50a9fae95a37a4c0e959d591a +Signed-off-by: Kamil Dudka +--- + lib/url.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 61ca8e8..92a126a 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4349,8 +4349,12 @@ static CURLcode parse_url_login(struct SessionHandle *data, + + /* Decode the user */ + newname = curl_easy_unescape(data, userp, 0, NULL); +- if(!newname) ++ if(!newname) { ++ Curl_safefree(userp); ++ Curl_safefree(passwdp); ++ Curl_safefree(optionsp); + return CURLE_OUT_OF_MEMORY; ++ } + + if(strlen(newname) < MAX_CURL_USER_LENGTH) + strcpy(user, newname); +@@ -4361,8 +4365,12 @@ static CURLcode parse_url_login(struct SessionHandle *data, + if(passwdp) { + /* We have a password in the URL so decode it */ + char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL); +- if(!newpasswd) ++ if(!newpasswd) { ++ Curl_safefree(userp); ++ Curl_safefree(passwdp); ++ Curl_safefree(optionsp); + return CURLE_OUT_OF_MEMORY; ++ } + + if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH) + strcpy(passwd, newpasswd); +@@ -4373,8 +4381,12 @@ static CURLcode parse_url_login(struct SessionHandle *data, + if(optionsp) { + /* We have an options list in the URL so decode it */ + char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL); +- if(!newoptions) ++ if(!newoptions) { ++ Curl_safefree(userp); ++ Curl_safefree(passwdp); ++ Curl_safefree(optionsp); + return CURLE_OUT_OF_MEMORY; ++ } + + if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH) + strcpy(options, newoptions); +-- +2.4.6 + + +From ca108f78f894fee22eadf46ec6ef4282d1f23949 Mon Sep 17 00:00:00 2001 +From: Jonathan Nieder +Date: Mon, 19 Aug 2013 00:38:08 -0700 +Subject: [PATCH 19/28] url: use goto in create_conn() for exception handling + +Instead of remembering before each "return" statement which temporary +allocations, if any, need to be freed, take care to set pointers to +NULL when no longer needed and use a goto to a common block to exit +the function and free all temporaries. + +No functional change intended. Currently the only temporary buffer in +this function is "proxy" which is already correctly freed when +appropriate, but there will be more soon. + +Upstream-commit: 53333a43a1959ddeef27c26f0983be1b81e558bc +Signed-off-by: Kamil Dudka +--- + lib/url.c | 64 +++++++++++++++++++++++++++++++++++++-------------------------- + 1 file changed, 38 insertions(+), 26 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 92a126a..105f2fe 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4924,8 +4924,10 @@ static CURLcode create_conn(struct SessionHandle *data, + * Check input data + *************************************************************/ + +- if(!data->change.url) +- return CURLE_URL_MALFORMAT; ++ if(!data->change.url) { ++ result = CURLE_URL_MALFORMAT; ++ goto out; ++ } + + /* First, split up the current URL in parts so that we can use the + parts for checking against the already present connections. In order +@@ -4933,8 +4935,10 @@ static CURLcode create_conn(struct SessionHandle *data, + connection data struct and fill in for comparison purposes. */ + conn = allocate_conn(data); + +- if(!conn) +- return CURLE_OUT_OF_MEMORY; ++ if(!conn) { ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; ++ } + + /* We must set the return variable as soon as possible, so that our + parent can cleanup any possible allocs we may have done before +@@ -4964,15 +4968,18 @@ static CURLcode create_conn(struct SessionHandle *data, + data->state.path = NULL; + + data->state.pathbuffer = malloc(urllen+2); +- if(NULL == data->state.pathbuffer) +- return CURLE_OUT_OF_MEMORY; /* really bad error */ ++ if(NULL == data->state.pathbuffer) { ++ result = CURLE_OUT_OF_MEMORY; /* really bad error */ ++ goto out; ++ } + data->state.path = data->state.pathbuffer; + + conn->host.rawalloc = malloc(urllen+2); + if(NULL == conn->host.rawalloc) { + Curl_safefree(data->state.pathbuffer); + data->state.path = NULL; +- return CURLE_OUT_OF_MEMORY; ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; + } + + conn->host.name = conn->host.rawalloc; +@@ -4981,7 +4988,7 @@ static CURLcode create_conn(struct SessionHandle *data, + result = parseurlandfillconn(data, conn, &prot_missing, user, passwd, + options); + if(result != CURLE_OK) +- return result; ++ goto out; + + /************************************************************* + * No protocol part in URL was used, add it! +@@ -4995,8 +5002,8 @@ static CURLcode create_conn(struct SessionHandle *data, + reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url); + + if(!reurl) { +- Curl_safefree(proxy); +- return CURLE_OUT_OF_MEMORY; ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; + } + + if(data->change.url_alloc) { +@@ -5033,7 +5040,7 @@ static CURLcode create_conn(struct SessionHandle *data, + if(conn->bits.proxy_user_passwd) { + result = parse_proxy_auth(data, conn); + if(result != CURLE_OK) +- return result; ++ goto out; + } + + /************************************************************* +@@ -5044,7 +5051,8 @@ static CURLcode create_conn(struct SessionHandle *data, + /* if global proxy is set, this is it */ + if(NULL == proxy) { + failf(data, "memory shortage"); +- return CURLE_OUT_OF_MEMORY; ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; + } + } + +@@ -5072,16 +5080,17 @@ static CURLcode create_conn(struct SessionHandle *data, + if(proxy) { + result = parse_proxy(data, conn, proxy); + +- free(proxy); /* parse_proxy copies the proxy string */ ++ Curl_safefree(proxy); /* parse_proxy copies the proxy string */ + + if(result) +- return result; ++ goto out; + + if((conn->proxytype == CURLPROXY_HTTP) || + (conn->proxytype == CURLPROXY_HTTP_1_0)) { + #ifdef CURL_DISABLE_HTTP + /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */ +- return CURLE_UNSUPPORTED_PROTOCOL; ++ result = CURLE_UNSUPPORTED_PROTOCOL; ++ goto out; + #else + /* force this connection's protocol to become HTTP if not already + compatible - if it isn't tunneling through */ +@@ -5111,10 +5120,8 @@ static CURLcode create_conn(struct SessionHandle *data, + * we figured out what/if proxy to use. + *************************************************************/ + result = setup_connection_internals(conn); +- if(result != CURLE_OK) { +- Curl_safefree(proxy); +- return result; +- } ++ if(result != CURLE_OK) ++ goto out; + + conn->recv[FIRSTSOCKET] = Curl_recv_plain; + conn->send[FIRSTSOCKET] = Curl_send_plain; +@@ -5147,7 +5154,7 @@ static CURLcode create_conn(struct SessionHandle *data, + DEBUGASSERT(conn->handler->done); + /* we ignore the return code for the protocol-specific DONE */ + (void)conn->handler->done(conn, result, FALSE); +- return result; ++ goto out; + } + + Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */ +@@ -5157,7 +5164,7 @@ static CURLcode create_conn(struct SessionHandle *data, + /* since we skip do_init() */ + Curl_speedinit(data); + +- return result; ++ goto out; + } + #endif + +@@ -5173,13 +5180,13 @@ static CURLcode create_conn(struct SessionHandle *data, + *************************************************************/ + result = parse_remote_port(data, conn); + if(result != CURLE_OK) +- return result; ++ goto out; + + /* Check for overridden login details and set them accordingly */ + override_login(data, conn, user, passwd, options); + result = set_login(conn, user, passwd, options); + if(result != CURLE_OK) +- return result; ++ goto out; + + /* Get a cloned copy of the SSL config situation stored in the + connection struct. But to get this going nicely, we must first make +@@ -5202,8 +5209,10 @@ static CURLcode create_conn(struct SessionHandle *data, + data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD]; + #endif + +- if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) +- return CURLE_OUT_OF_MEMORY; ++ if(!Curl_clone_ssl_config(&data->set.ssl, &conn->ssl_config)) { ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; ++ } + + /************************************************************* + * Check the current list of connections to see if we can +@@ -5256,7 +5265,7 @@ static CURLcode create_conn(struct SessionHandle *data, + */ + result = setup_range(data); + if(result) +- return result; ++ goto out; + + /* Continue connectdata initialization here. */ + +@@ -5274,6 +5283,9 @@ static CURLcode create_conn(struct SessionHandle *data, + *************************************************************/ + result = resolve_server(data, conn, async); + ++ out: ++ ++ Curl_safefree(proxy); + return result; + } + +-- +2.4.6 + + +From 2f81fdaa7a966ba8e0bfaae29d86426b7e8159bd Mon Sep 17 00:00:00 2001 +From: Jonathan Nieder +Date: Mon, 19 Aug 2013 00:39:05 -0700 +Subject: [PATCH 20/28] url: allocate username, password, and options on the + heap + +This makes it possible to increase the size of the buffers when needed +in later patches. No functional change yet. + +Upstream-commit: 11baffbff67eae225f63fc684d80ce52a79c8ac5 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 105f2fe..6bce0bb 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4911,9 +4911,9 @@ static CURLcode create_conn(struct SessionHandle *data, + struct connectdata *conn; + struct connectdata *conn_temp = NULL; + size_t urllen; +- char user[MAX_CURL_USER_LENGTH]; +- char passwd[MAX_CURL_PASSWORD_LENGTH]; +- char options[MAX_CURL_OPTIONS_LENGTH]; ++ char *user = NULL; ++ char *passwd = NULL; ++ char *options = NULL; + bool reuse; + char *proxy = NULL; + bool prot_missing = FALSE; +@@ -4985,6 +4985,14 @@ static CURLcode create_conn(struct SessionHandle *data, + conn->host.name = conn->host.rawalloc; + conn->host.name[0] = 0; + ++ user = malloc(MAX_CURL_USER_LENGTH); ++ passwd = malloc(MAX_CURL_PASSWORD_LENGTH); ++ options = malloc(MAX_CURL_OPTIONS_LENGTH); ++ if(!user || !passwd || !options) { ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; ++ } ++ + result = parseurlandfillconn(data, conn, &prot_missing, user, passwd, + options); + if(result != CURLE_OK) +@@ -5285,6 +5293,9 @@ static CURLcode create_conn(struct SessionHandle *data, + + out: + ++ Curl_safefree(options); ++ Curl_safefree(passwd); ++ Curl_safefree(user); + Curl_safefree(proxy); + return result; + } +-- +2.4.6 + + +From 978711e025bcbd1654758b648db4317d0e446f84 Mon Sep 17 00:00:00 2001 +From: Jonathan Nieder +Date: Mon, 19 Aug 2013 00:48:24 -0700 +Subject: [PATCH 21/28] netrc: handle longer username and password + +libcurl truncates usernames and passwords it reads from .netrc to +LOGINSIZE and PASSWORDSIZE (64) characters without any indication to +the user, to ensure the values returned from Curl_parsenetrc fit in a +caller-provided buffer. + +Fix the interface by passing back dynamically allocated buffers +allocated to fit the user's input. The parser still relies on a +256-character buffer to read each line, though. + +So now you can include an ~246-character password in your .netrc, +instead of the previous limit of 63 characters. + +Reported-by: Colby Ranger + +Upstream-commit: 36585b539543ca4471ab19c0d738a6e52a827aee +Signed-off-by: Kamil Dudka +--- + lib/netrc.c | 20 ++++++++++++------- + lib/netrc.h | 16 ++++++---------- + lib/url.c | 18 ++++++++--------- + tests/unit/unit1304.c | 53 ++++++++++++++++++++++++++++++--------------------- + 4 files changed, 59 insertions(+), 48 deletions(-) + +diff --git a/lib/netrc.c b/lib/netrc.c +index 2c5942a..f51fdf3 100644 +--- a/lib/netrc.c ++++ b/lib/netrc.c +@@ -52,13 +52,13 @@ enum host_lookup_state { + * @unittest: 1304 + */ + int Curl_parsenetrc(const char *host, +- char *login, +- char *password, ++ char **loginp, ++ char **passwordp, + char *netrcfile) + { + FILE *file; + int retcode=1; +- int specific_login = (login[0] != 0); ++ int specific_login = (**loginp != 0); + char *home = NULL; + bool home_alloc = FALSE; + bool netrc_alloc = FALSE; +@@ -109,7 +109,7 @@ int Curl_parsenetrc(const char *host, + tok=strtok_r(netrcbuffer, " \t\n", &tok_buf); + while(!done && tok) { + +- if(login[0] && password[0]) { ++ if(**loginp && **passwordp) { + done=TRUE; + break; + } +@@ -138,16 +138,22 @@ int Curl_parsenetrc(const char *host, + /* we are now parsing sub-keywords concerning "our" host */ + if(state_login) { + if(specific_login) { +- state_our_login = Curl_raw_equal(login, tok); ++ state_our_login = Curl_raw_equal(*loginp, tok); + } + else { +- strncpy(login, tok, LOGINSIZE-1); ++ free(*loginp); ++ *loginp = strdup(tok); ++ if(!*loginp) ++ return -1; /* allocation failed */ + } + state_login=0; + } + else if(state_password) { + if(state_our_login || !specific_login) { +- strncpy(password, tok, PASSWORDSIZE-1); ++ free(*passwordp); ++ *passwordp = strdup(tok); ++ if(!*passwordp) ++ return -1; /* allocation failed */ + } + state_password=0; + } +diff --git a/lib/netrc.h b/lib/netrc.h +index 4db764d..a145601 100644 +--- a/lib/netrc.h ++++ b/lib/netrc.h +@@ -22,19 +22,15 @@ + * + ***************************************************************************/ + +-/* Make sure we have room for at least this size: */ +-#define LOGINSIZE 64 +-#define PASSWORDSIZE 64 +- + /* returns -1 on failure, 0 if the host is found, 1 is the host isn't found */ + int Curl_parsenetrc(const char *host, +- char *login, +- char *password, ++ char **loginp, ++ char **passwordp, + char *filename); +- /* Assume: password[0]=0, host[0] != 0. +- * If login[0] = 0, search for login and password within a machine section +- * in the netrc. +- * If login[0] != 0, search for password within machine and login. ++ /* Assume: (*passwordp)[0]=0, host[0] != 0. ++ * If (*loginp)[0] = 0, search for login and password within a machine ++ * section in the netrc. ++ * If (*loginp)[0] != 0, search for password within machine and login. + */ + + #endif /* HEADER_CURL_NETRC_H */ +diff --git a/lib/url.c b/lib/url.c +index 6bce0bb..406ef85 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4656,27 +4656,27 @@ static CURLcode parse_remote_port(struct SessionHandle *data, + */ + static void override_login(struct SessionHandle *data, + struct connectdata *conn, +- char *user, char *passwd, char *options) ++ char **userp, char **passwdp, char **optionsp) + { + if(data->set.str[STRING_USERNAME]) { +- strncpy(user, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH); +- user[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */ ++ strncpy(*userp, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH); ++ (*userp)[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */ + } + + if(data->set.str[STRING_PASSWORD]) { +- strncpy(passwd, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH); +- passwd[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */ ++ strncpy(*passwdp, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH); ++ (*passwdp)[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */ + } + + if(data->set.str[STRING_OPTIONS]) { +- strncpy(options, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH); +- options[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */ ++ strncpy(*optionsp, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH); ++ (*optionsp)[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */ + } + + conn->bits.netrc = FALSE; + if(data->set.use_netrc != CURL_NETRC_IGNORED) { + if(Curl_parsenetrc(conn->host.name, +- user, passwd, ++ userp, passwdp, + data->set.str[STRING_NETRC_FILE])) { + infof(data, "Couldn't find host %s in the " + DOT_CHAR "netrc file; using defaults\n", +@@ -5191,7 +5191,7 @@ static CURLcode create_conn(struct SessionHandle *data, + goto out; + + /* Check for overridden login details and set them accordingly */ +- override_login(data, conn, user, passwd, options); ++ override_login(data, conn, &user, &passwd, &options); + result = set_login(conn, user, passwd, options); + if(result != CURLE_OK) + goto out; +diff --git a/tests/unit/unit1304.c b/tests/unit/unit1304.c +index 8ddd8ca..9242e80 100644 +--- a/tests/unit/unit1304.c ++++ b/tests/unit/unit1304.c +@@ -23,14 +23,14 @@ + + #include "netrc.h" + +-static char login[LOGINSIZE]; +-static char password[PASSWORDSIZE]; ++static char *login; ++static char *password; + static char filename[64]; + + static CURLcode unit_setup(void) + { +- password[0] = 0; +- login[0] = 0; ++ password = strdup(""); ++ login = strdup(""); + return CURLE_OK; + } + +@@ -47,7 +47,7 @@ UNITTEST_START + /* + * Test a non existent host in our netrc file. + */ +- result = Curl_parsenetrc("test.example.com", login, password, filename); ++ result = Curl_parsenetrc("test.example.com", &login, &password, filename); + fail_unless(result == 1, "Host not found should return 1"); + fail_unless(password[0] == 0, "password should not have been changed"); + fail_unless(login[0] == 0, "login should not have been changed"); +@@ -55,8 +55,9 @@ UNITTEST_START + /* + * Test a non existent login in our netrc file. + */ +- memcpy(login, "me", 2); +- result = Curl_parsenetrc("example.com", login, password, filename); ++ free(login); ++ login = strdup("me"); ++ result = Curl_parsenetrc("example.com", &login, &password, filename); + fail_unless(result == 0, "Host should be found"); + fail_unless(password[0] == 0, "password should not have been changed"); + fail_unless(strncmp(login, "me", 2) == 0, "login should not have been changed"); +@@ -64,8 +65,9 @@ UNITTEST_START + /* + * Test a non existent login and host in our netrc file. + */ +- memcpy(login, "me", 2); +- result = Curl_parsenetrc("test.example.com", login, password, filename); ++ free(login); ++ login = strdup("me"); ++ result = Curl_parsenetrc("test.example.com", &login, &password, filename); + fail_unless(result == 1, "Host should be found"); + fail_unless(password[0] == 0, "password should not have been changed"); + fail_unless(strncmp(login, "me", 2) == 0, "login should not have been changed"); +@@ -74,8 +76,9 @@ UNITTEST_START + * Test a non existent login (substring of an existing one) in our + * netrc file. + */ +- memcpy(login, "admi", 4); +- result = Curl_parsenetrc("example.com", login, password, filename); ++ free(login); ++ login = strdup("admi"); ++ result = Curl_parsenetrc("example.com", &login, &password, filename); + fail_unless(result == 0, "Host should be found"); + fail_unless(password[0] == 0, "password should not have been changed"); + fail_unless(strncmp(login, "admi", 4) == 0, "login should not have been changed"); +@@ -84,8 +87,9 @@ UNITTEST_START + * Test a non existent login (superstring of an existing one) + * in our netrc file. + */ +- memcpy(login, "adminn", 6); +- result = Curl_parsenetrc("example.com", login, password, filename); ++ free(login); ++ login = strdup("adminn"); ++ result = Curl_parsenetrc("example.com", &login, &password, filename); + fail_unless(result == 0, "Host should be found"); + fail_unless(password[0] == 0, "password should not have been changed"); + fail_unless(strncmp(login, "adminn", 6) == 0, "login should not have been changed"); +@@ -94,8 +98,9 @@ UNITTEST_START + * Test for the first existing host in our netrc file + * with login[0] = 0. + */ +- login[0] = 0; +- result = Curl_parsenetrc("example.com", login, password, filename); ++ free(login); ++ login = strdup(""); ++ result = Curl_parsenetrc("example.com", &login, &password, filename); + fail_unless(result == 0, "Host should have been found"); + fail_unless(strncmp(password, "passwd", 6) == 0, + "password should be 'passwd'"); +@@ -105,8 +110,9 @@ UNITTEST_START + * Test for the first existing host in our netrc file + * with login[0] != 0. + */ +- password[0] = 0; +- result = Curl_parsenetrc("example.com", login, password, filename); ++ free(password); ++ password = strdup(""); ++ result = Curl_parsenetrc("example.com", &login, &password, filename); + fail_unless(result == 0, "Host should have been found"); + fail_unless(strncmp(password, "passwd", 6) == 0, + "password should be 'passwd'"); +@@ -116,9 +122,11 @@ UNITTEST_START + * Test for the second existing host in our netrc file + * with login[0] = 0. + */ +- password[0] = 0; +- login[0] = 0; +- result = Curl_parsenetrc("curl.example.com", login, password, filename); ++ free(password); ++ password = strdup(""); ++ free(login); ++ login = strdup(""); ++ result = Curl_parsenetrc("curl.example.com", &login, &password, filename); + fail_unless(result == 0, "Host should have been found"); + fail_unless(strncmp(password, "none", 4) == 0, + "password should be 'none'"); +@@ -128,8 +136,9 @@ UNITTEST_START + * Test for the second existing host in our netrc file + * with login[0] != 0. + */ +- password[0] = 0; +- result = Curl_parsenetrc("curl.example.com", login, password, filename); ++ free(password); ++ password = strdup(""); ++ result = Curl_parsenetrc("curl.example.com", &login, &password, filename); + fail_unless(result == 0, "Host should have been found"); + fail_unless(strncmp(password, "none", 4) == 0, + "password should be 'none'"); +-- +2.4.6 + + +From 96b625ddedb692a41b173cabf0bd5913f4535c70 Mon Sep 17 00:00:00 2001 +From: Jonathan Nieder +Date: Mon, 19 Aug 2013 00:57:54 -0700 +Subject: [PATCH 22/28] Curl_setopt: handle arbitrary-length username and + password + +libcurl truncates usernames, passwords, and options set with +curl_easy_setopt to 255 (= MAX_CURL_PASSWORD_LENGTH - 1) characters. +This doesn't affect the return value from curl_easy_setopt(), so from +the caller's point of view, there is no sign anything strange has +happened, except that authentication fails. + +For example: + + # Prepare a long (300-char) password. + s=0123456789; s=$s$s$s$s$s$s$s$s$s$s; s=$s$s$s; + # Start a server. + nc -l -p 8888 | tee out & pid=$! + # Tell curl to pass the password to the server. + curl --user me:$s http://localhost:8888 & sleep 1; kill $pid + # Extract the password. + userpass=$( + awk '/Authorization: Basic/ {print $3}' +--- + lib/url.c | 29 +++++++++++++++++++---------- + 1 file changed, 19 insertions(+), 10 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 406ef85..515fa67 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4654,23 +4654,29 @@ static CURLcode parse_remote_port(struct SessionHandle *data, + * Override the login details from the URL with that in the CURLOPT_USERPWD + * option or a .netrc file, if applicable. + */ +-static void override_login(struct SessionHandle *data, +- struct connectdata *conn, +- char **userp, char **passwdp, char **optionsp) ++static int override_login(struct SessionHandle *data, ++ struct connectdata *conn, ++ char **userp, char **passwdp, char **optionsp) + { + if(data->set.str[STRING_USERNAME]) { +- strncpy(*userp, data->set.str[STRING_USERNAME], MAX_CURL_USER_LENGTH); +- (*userp)[MAX_CURL_USER_LENGTH - 1] = '\0'; /* To be on safe side */ ++ free(*userp); ++ *userp = strdup(data->set.str[STRING_USERNAME]); ++ if(!*userp) ++ return CURLE_OUT_OF_MEMORY; + } + + if(data->set.str[STRING_PASSWORD]) { +- strncpy(*passwdp, data->set.str[STRING_PASSWORD], MAX_CURL_PASSWORD_LENGTH); +- (*passwdp)[MAX_CURL_PASSWORD_LENGTH - 1] = '\0'; /* To be on safe side */ ++ free(*passwdp); ++ *passwdp = strdup(data->set.str[STRING_PASSWORD]); ++ if(!*passwdp) ++ return CURLE_OUT_OF_MEMORY; + } + + if(data->set.str[STRING_OPTIONS]) { +- strncpy(*optionsp, data->set.str[STRING_OPTIONS], MAX_CURL_OPTIONS_LENGTH); +- (*optionsp)[MAX_CURL_OPTIONS_LENGTH - 1] = '\0'; /* To be on safe side */ ++ free(*optionsp); ++ *optionsp = strdup(data->set.str[STRING_OPTIONS]); ++ if(!*optionsp) ++ return CURLE_OUT_OF_MEMORY; + } + + conn->bits.netrc = FALSE; +@@ -4691,6 +4697,7 @@ static void override_login(struct SessionHandle *data, + conn->bits.user_passwd = TRUE; /* enable user+password */ + } + } ++ return CURLE_OK; + } + + /* +@@ -5191,7 +5198,9 @@ static CURLcode create_conn(struct SessionHandle *data, + goto out; + + /* Check for overridden login details and set them accordingly */ +- override_login(data, conn, &user, &passwd, &options); ++ result = override_login(data, conn, &user, &passwd, &options); ++ if(result != CURLE_OK) ++ goto out; + result = set_login(conn, user, passwd, options); + if(result != CURLE_OK) + goto out; +-- +2.4.6 + + +From d2fa706f006d393eee63ed686efccf68db5b6337 Mon Sep 17 00:00:00 2001 +From: Jonathan Nieder +Date: Mon, 19 Aug 2013 01:01:26 -0700 +Subject: [PATCH 23/28] url: handle exceptional cases first in + parse_url_login() + +Instead of nesting "if(success)" blocks and leaving the reader in +suspense about what happens in the !success case, deal with failure +cases early, usually with a simple goto to clean up and return from +the function. + +No functional change intended. The main effect is to decrease the +indentation of this function slightly. + +Upstream-commit: 09ddb1d61cdb9ee11ebf481b29dac1be8f0ab848 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 121 ++++++++++++++++++++++++++++++-------------------------------- + 1 file changed, 59 insertions(+), 62 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 515fa67..8fff5ef 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4321,86 +4321,83 @@ static CURLcode parse_url_login(struct SessionHandle *data, + passwd[0] = 0; + options[0] = 0; + ++ if(!ptr) ++ goto out; ++ + /* We will now try to extract the + * possible login information in a string like: + * ftp://user:password@ftp.my.site:8021/README */ +- if(ptr) { +- /* There's login information to the left of the @ */ ++ conn->host.name = ++ptr; + +- conn->host.name = ++ptr; ++ /* So the hostname is sane. Only bother interpreting the ++ * results if we could care. It could still be wasted ++ * work because it might be overtaken by the programmatically ++ * set user/passwd, but doing that first adds more cases here :-( ++ */ + +- /* So the hostname is sane. Only bother interpreting the +- * results if we could care. It could still be wasted +- * work because it might be overtaken by the programmatically +- * set user/passwd, but doing that first adds more cases here :-( +- */ ++ if(data->set.use_netrc == CURL_NETRC_REQUIRED) ++ goto out; + +- if(data->set.use_netrc != CURL_NETRC_REQUIRED) { +- /* We could use the login information in the URL so extract it */ +- result = parse_login_details(login, ptr - login - 1, +- &userp, &passwdp, &optionsp); +- if(!result) { +- if(userp) { +- char *newname; +- +- /* We have a user in the URL */ +- conn->bits.userpwd_in_url = TRUE; +- conn->bits.user_passwd = TRUE; /* enable user+password */ +- +- /* Decode the user */ +- newname = curl_easy_unescape(data, userp, 0, NULL); +- if(!newname) { +- Curl_safefree(userp); +- Curl_safefree(passwdp); +- Curl_safefree(optionsp); +- return CURLE_OUT_OF_MEMORY; +- } ++ /* We could use the login information in the URL so extract it */ ++ result = parse_login_details(login, ptr - login - 1, ++ &userp, &passwdp, &optionsp); ++ if(result != CURLE_OK) ++ goto out; + +- if(strlen(newname) < MAX_CURL_USER_LENGTH) +- strcpy(user, newname); ++ if(userp) { ++ char *newname; + +- free(newname); +- } ++ /* We have a user in the URL */ ++ conn->bits.userpwd_in_url = TRUE; ++ conn->bits.user_passwd = TRUE; /* enable user+password */ + +- if(passwdp) { +- /* We have a password in the URL so decode it */ +- char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL); +- if(!newpasswd) { +- Curl_safefree(userp); +- Curl_safefree(passwdp); +- Curl_safefree(optionsp); +- return CURLE_OUT_OF_MEMORY; +- } ++ /* Decode the user */ ++ newname = curl_easy_unescape(data, userp, 0, NULL); ++ if(!newname) { ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; ++ } + +- if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH) +- strcpy(passwd, newpasswd); ++ if(strlen(newname) < MAX_CURL_USER_LENGTH) ++ strcpy(user, newname); + +- free(newpasswd); +- } ++ free(newname); ++ } + +- if(optionsp) { +- /* We have an options list in the URL so decode it */ +- char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL); +- if(!newoptions) { +- Curl_safefree(userp); +- Curl_safefree(passwdp); +- Curl_safefree(optionsp); +- return CURLE_OUT_OF_MEMORY; +- } ++ if(passwdp) { ++ /* We have a password in the URL so decode it */ ++ char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL); ++ if(!newpasswd) { ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; ++ } + +- if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH) +- strcpy(options, newoptions); ++ if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH) ++ strcpy(passwd, newpasswd); + +- free(newoptions); +- } +- } ++ free(newpasswd); ++ } + +- Curl_safefree(userp); +- Curl_safefree(passwdp); +- Curl_safefree(optionsp); ++ if(optionsp) { ++ /* We have an options list in the URL so decode it */ ++ char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL); ++ if(!newoptions) { ++ result = CURLE_OUT_OF_MEMORY; ++ goto out; + } ++ ++ if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH) ++ strcpy(options, newoptions); ++ ++ free(newoptions); + } + ++ out: ++ ++ Curl_safefree(userp); ++ Curl_safefree(passwdp); ++ Curl_safefree(optionsp); ++ + return result; + } + +-- +2.4.6 + + +From 085588f8f1baa68a28e0cc3b7197fcb3f99b8f15 Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sun, 21 Apr 2013 12:11:50 +0100 +Subject: [PATCH 24/28] url: Removed unused text length constants + +Upstream-commit: 455ba691a7250b312075a5d91ae89bbbe70d62aa +Signed-off-by: Kamil Dudka +--- + lib/urldata.h | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/lib/urldata.h b/lib/urldata.h +index 1c2281a..219a11a 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1134,9 +1134,6 @@ typedef enum { + #define MAX_CURL_USER_LENGTH 256 + #define MAX_CURL_PASSWORD_LENGTH 256 + #define MAX_CURL_OPTIONS_LENGTH 256 +-#define MAX_CURL_USER_LENGTH_TXT "255" +-#define MAX_CURL_PASSWORD_LENGTH_TXT "255" +-#define MAX_CURL_OPTIONS_LENGTH_TXT "255" + + struct auth { + unsigned long want; /* Bitmask set to the authentication methods wanted by +-- +2.4.6 + + +From 314f6398307783780f416d834295002c4b745251 Mon Sep 17 00:00:00 2001 +From: Jonathan Nieder +Date: Mon, 19 Aug 2013 01:36:46 -0700 +Subject: [PATCH 25/28] url: handle arbitrary-length username and password + before '@' + +libcurl quietly truncates usernames, passwords, and options from +before an '@' sign in a URL to 255 (= MAX_CURL_PASSWORD_LENGTH - 1) +characters to fit in fixed-size buffers on the stack. Allocate a +buffer large enough to fit the parsed fields on the fly instead to +support longer passwords. + +After this change, there are no more uses of MAX_CURL_OPTIONS_LENGTH +left, so stop defining that constant while at it. The hardcoded max +username and password length constants, on the other hand, are still +used in HTTP proxy credential handling (which this patch doesn't +touch). + +Reported-by: Colby Ranger + +Upstream-commit: 2f1a0bc0bf36c5ad0f8755d9c7553e1f5729af43 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 45 +++++++++++++++++++++------------------------ + lib/urldata.h | 1 - + 2 files changed, 21 insertions(+), 25 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 8fff5ef..abf8a43 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -140,7 +140,8 @@ static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke); + static CURLcode do_init(struct connectdata *conn); + static CURLcode parse_url_login(struct SessionHandle *data, + struct connectdata *conn, +- char *user, char *passwd, char *options); ++ char **userptr, char **passwdptr, ++ char **optionsptr); + static CURLcode parse_login_details(const char *login, const size_t len, + char **userptr, char **passwdptr, + char **optionsptr); +@@ -3595,7 +3596,8 @@ static CURLcode findprotocol(struct SessionHandle *data, + static CURLcode parseurlandfillconn(struct SessionHandle *data, + struct connectdata *conn, + bool *prot_missing, +- char *user, char *passwd, char *options) ++ char **userp, char **passwdp, ++ char **optionsp) + { + char *at; + char *fragment; +@@ -3820,7 +3822,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data, + * Parse the login details from the URL and strip them out of + * the host name + */ +- result = parse_url_login(data, conn, user, passwd, options); ++ result = parse_url_login(data, conn, userp, passwdp, optionsp); + if(result != CURLE_OK) + return result; + +@@ -4300,7 +4302,7 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data, + */ + static CURLcode parse_url_login(struct SessionHandle *data, + struct connectdata *conn, +- char *user, char *passwd, char *options) ++ char **user, char **passwd, char **options) + { + CURLcode result = CURLE_OK; + char *userp = NULL; +@@ -4317,9 +4319,9 @@ static CURLcode parse_url_login(struct SessionHandle *data, + char *ptr = strchr(conn->host.name, '@'); + char *login = conn->host.name; + +- user[0] = 0; /* to make everything well-defined */ +- passwd[0] = 0; +- options[0] = 0; ++ DEBUGASSERT(!**user); ++ DEBUGASSERT(!**passwd); ++ DEBUGASSERT(!**options); + + if(!ptr) + goto out; +@@ -4358,10 +4360,8 @@ static CURLcode parse_url_login(struct SessionHandle *data, + goto out; + } + +- if(strlen(newname) < MAX_CURL_USER_LENGTH) +- strcpy(user, newname); +- +- free(newname); ++ free(*user); ++ *user = newname; + } + + if(passwdp) { +@@ -4372,10 +4372,8 @@ static CURLcode parse_url_login(struct SessionHandle *data, + goto out; + } + +- if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH) +- strcpy(passwd, newpasswd); +- +- free(newpasswd); ++ free(*passwd); ++ *passwd = newpasswd; + } + + if(optionsp) { +@@ -4386,12 +4384,11 @@ static CURLcode parse_url_login(struct SessionHandle *data, + goto out; + } + +- if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH) +- strcpy(options, newoptions); +- +- free(newoptions); ++ free(*options); ++ *options = newoptions; + } + ++ + out: + + Curl_safefree(userp); +@@ -4989,16 +4986,16 @@ static CURLcode create_conn(struct SessionHandle *data, + conn->host.name = conn->host.rawalloc; + conn->host.name[0] = 0; + +- user = malloc(MAX_CURL_USER_LENGTH); +- passwd = malloc(MAX_CURL_PASSWORD_LENGTH); +- options = malloc(MAX_CURL_OPTIONS_LENGTH); ++ user = strdup(""); ++ passwd = strdup(""); ++ options = strdup(""); + if(!user || !passwd || !options) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + +- result = parseurlandfillconn(data, conn, &prot_missing, user, passwd, +- options); ++ result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd, ++ &options); + if(result != CURLE_OK) + goto out; + +diff --git a/lib/urldata.h b/lib/urldata.h +index 219a11a..b3ee7e3 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1133,7 +1133,6 @@ typedef enum { + * Session-data MUST be put in the connectdata struct and here. */ + #define MAX_CURL_USER_LENGTH 256 + #define MAX_CURL_PASSWORD_LENGTH 256 +-#define MAX_CURL_OPTIONS_LENGTH 256 + + struct auth { + unsigned long want; /* Bitmask set to the authentication methods wanted by +-- +2.4.6 + + +From 806203027b9dae8992f9762b056e953ecb118b84 Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Sun, 1 Sep 2013 13:30:12 +0100 +Subject: [PATCH 26/28] url.c: Fixed compilation warning + +An enumerated type is mixed with another type + +Upstream-commit: 322f0bc2f1af4a985e85ee5c8639e3b454314ccd +Signed-off-by: Kamil Dudka +--- + lib/url.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index abf8a43..558799c 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4648,9 +4648,9 @@ static CURLcode parse_remote_port(struct SessionHandle *data, + * Override the login details from the URL with that in the CURLOPT_USERPWD + * option or a .netrc file, if applicable. + */ +-static int override_login(struct SessionHandle *data, +- struct connectdata *conn, +- char **userp, char **passwdp, char **optionsp) ++static CURLcode override_login(struct SessionHandle *data, ++ struct connectdata *conn, ++ char **userp, char **passwdp, char **optionsp) + { + if(data->set.str[STRING_USERNAME]) { + free(*userp); +@@ -4691,6 +4691,7 @@ static int override_login(struct SessionHandle *data, + conn->bits.user_passwd = TRUE; /* enable user+password */ + } + } ++ + return CURLE_OK; + } + +-- +2.4.6 + + +From 7ed75f9bce576390e2c94a797c4520130654b416 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 14 Dec 2013 22:39:27 +0100 +Subject: [PATCH 27/28] login options: remove the ;[options] support from + CURLOPT_USERPWD + +To avoid the regression when users pass in passwords containing semi- +colons, we now drop the ability to set the login options with the same +options. Support for login options in CURLOPT_USERPWD was added in +7.31.0. + +Test case 83 was modified to verify that colons and semi-colons can be +used as part of the password when using -u (CURLOPT_USERPWD). + +Bug: http://curl.haxx.se/bug/view.cgi?id=1311 +Reported-by: Petr Bahula +Assisted-by: Steve Holme +Signed-off-by: Daniel Stenberg + +Upstream-commit: 169fedbdce93ecf14befb6e0e1ce6a2d480252a3 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 19 +++++-------------- + tests/data/test83 | 4 ++-- + 2 files changed, 7 insertions(+), 16 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 558799c..8c76256 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -295,13 +295,11 @@ static CURLcode setstropt(char **charp, char *s) + return CURLE_OK; + } + +-static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp, +- char **optionsp) ++static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp) + { + CURLcode result = CURLE_OK; + char *user = NULL; + char *passwd = NULL; +- char *options = NULL; + + /* Parse the login details if specified. It not then we treat NULL as a hint + to clear the existing data */ +@@ -309,7 +307,7 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp, + result = parse_login_details(option, strlen(option), + (userp ? &user : NULL), + (passwdp ? &passwd : NULL), +- (optionsp ? &options : NULL)); ++ NULL); + } + + if(!result) { +@@ -331,12 +329,6 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp, + Curl_safefree(*passwdp); + *passwdp = passwd; + } +- +- /* Store the options part of option if required */ +- if(optionsp) { +- Curl_safefree(*optionsp); +- *optionsp = options; +- } + } + + return result; +@@ -1553,12 +1545,11 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, + + case CURLOPT_USERPWD: + /* +- * user:password;options to use in the operation ++ * user:password to use in the operation + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_USERNAME], +- &data->set.str[STRING_PASSWORD], +- &data->set.str[STRING_OPTIONS]); ++ &data->set.str[STRING_PASSWORD]); + break; + case CURLOPT_USERNAME: + /* +@@ -1631,7 +1622,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, + */ + result = setstropt_userpwd(va_arg(param, char *), + &data->set.str[STRING_PROXYUSERNAME], +- &data->set.str[STRING_PROXYPASSWORD], NULL); ++ &data->set.str[STRING_PROXYPASSWORD]); + break; + case CURLOPT_PROXYUSERNAME: + /* +diff --git a/tests/data/test83 b/tests/data/test83 +index 3015c9c..160b40c 100644 +--- a/tests/data/test83 ++++ b/tests/data/test83 +@@ -46,7 +46,7 @@ http-proxy + HTTP over proxy-tunnel with site authentication + + +-http://%HOSTIP:%HTTPPORT/we/want/that/page/83 -p -x %HOSTIP:%PROXYPORT --user iam:myself ++http://%HOSTIP:%HTTPPORT/we/want/that/page/83 -p -x %HOSTIP:%PROXYPORT --user 'iam:my:;self' + + + +@@ -65,7 +65,7 @@ Proxy-Connection: Keep-Alive + + + GET /we/want/that/page/83 HTTP/1.1 +-Authorization: Basic aWFtOm15c2VsZg== ++Authorization: Basic aWFtOm15OjtzZWxm + User-Agent: curl/7.10.7-pre2 (i686-pc-linux-gnu) libcurl/7.10.7-pre2 OpenSSL/0.9.7a zlib/1.1.3 + Host: %HOSTIP:%HTTPPORT + Accept: */* +-- +2.4.6 + + +From ffe3cb2b365e914e364a6c9d7611e6e7f60d3cfa Mon Sep 17 00:00:00 2001 +From: Dan Fandrich +Date: Wed, 29 Jan 2014 08:10:26 +0100 +Subject: [PATCH 28/28] netrc: Fixed a memory leak in an OOM condition + +Upstream-commit: 768151449b386488ac8fe869f48bf2930123d601 +Signed-off-by: Kamil Dudka +--- + lib/url.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/lib/url.c b/lib/url.c +index 8c76256..57944e4 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -4666,13 +4666,17 @@ static CURLcode override_login(struct SessionHandle *data, + + conn->bits.netrc = FALSE; + if(data->set.use_netrc != CURL_NETRC_IGNORED) { +- if(Curl_parsenetrc(conn->host.name, +- userp, passwdp, +- data->set.str[STRING_NETRC_FILE])) { ++ int ret = Curl_parsenetrc(conn->host.name, ++ userp, passwdp, ++ data->set.str[STRING_NETRC_FILE]); ++ if(ret > 0) { + infof(data, "Couldn't find host %s in the " + DOT_CHAR "netrc file; using defaults\n", + conn->host.name); + } ++ else if(ret < 0 ) { ++ return CURLE_OUT_OF_MEMORY; ++ } + else { + /* set bits.netrc TRUE to remember that we got the name from a .netrc + file, so that it is safe to use even if we followed a Location: to a +-- +2.4.6 + diff --git a/SOURCES/0036-curl-7.29.0-c8644d1f.patch b/SOURCES/0036-curl-7.29.0-c8644d1f.patch new file mode 100644 index 0000000..7f631f8 --- /dev/null +++ b/SOURCES/0036-curl-7.29.0-c8644d1f.patch @@ -0,0 +1,2007 @@ +From 3fef242a1e1a74140a1678d84164086d0f47d83a Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Thu, 27 Nov 2014 23:59:19 +0100 +Subject: [PATCH 01/11] sws: move away from IPv4/IPv4-only assumption + +Instead of depending the socket domain type on use_ipv6, specify the +domain type (AF_INET / AF_INET6) as variable. An enum is used here with +switch to avoid compiler warnings in connect_to, complaining that rc +is possibly undefined (which is not possible as socket_domain is +always set). + +Besides abstracting the socket type, make the debugging messages be +independent on IP (introduce location_str which points to "port XXXXX"). +Rename "ipv_inuse" to "socket_type" and tighten the scope (main). + +Signed-off-by: Peter Wu + +Upstream-commit: cf6c5c222d86088cbfc9dee4c23f8ada96ee91e7 +Signed-off-by: Kamil Dudka +--- + tests/server/sws.c | 88 ++++++++++++++++++++++++------------------------------ + 1 file changed, 39 insertions(+), 49 deletions(-) + +diff --git a/tests/server/sws.c b/tests/server/sws.c +index aef55ea..fa10d54 100644 +--- a/tests/server/sws.c ++++ b/tests/server/sws.c +@@ -65,11 +65,13 @@ + #define ERANGE 34 /* errno.h value */ + #endif + ++static enum { ++ socket_domain_inet = AF_INET, + #ifdef ENABLE_IPV6 +-static bool use_ipv6 = FALSE; ++ socket_domain_inet6 = AF_INET6 + #endif ++} socket_domain = AF_INET; + static bool use_gopher = FALSE; +-static const char *ipv_inuse = "IPv4"; + static int serverlogslocked = 0; + static bool is_proxy = FALSE; + +@@ -1285,7 +1287,7 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) + #endif + + #ifdef ENABLE_IPV6 +- if(use_ipv6) { ++ if(socket_domain == AF_INET6) { + op_br = "["; + cl_br = "]"; + } +@@ -1297,14 +1299,8 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) + logmsg("about to connect to %s%s%s:%hu", + op_br, ipaddr, cl_br, port); + +-#ifdef ENABLE_IPV6 +- if(!use_ipv6) +-#endif +- serverfd = socket(AF_INET, SOCK_STREAM, 0); +-#ifdef ENABLE_IPV6 +- else +- serverfd = socket(AF_INET6, SOCK_STREAM, 0); +-#endif ++ ++ serverfd = socket(socket_domain, SOCK_STREAM, 0); + if(CURL_SOCKET_BAD == serverfd) { + error = SOCKERRNO; + logmsg("Error creating socket for server conection: (%d) %s", +@@ -1322,9 +1318,8 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) + logmsg("TCP_NODELAY set for server conection"); + #endif + +-#ifdef ENABLE_IPV6 +- if(!use_ipv6) { +-#endif ++ switch(socket_domain) { ++ case AF_INET: + memset(&serveraddr.sa4, 0, sizeof(serveraddr.sa4)); + serveraddr.sa4.sin_family = AF_INET; + serveraddr.sa4.sin_port = htons(port); +@@ -1335,9 +1330,9 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) + } + + rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa4)); ++ break; + #ifdef ENABLE_IPV6 +- } +- else { ++ case AF_INET6: + memset(&serveraddr.sa6, 0, sizeof(serveraddr.sa6)); + serveraddr.sa6.sin6_family = AF_INET6; + serveraddr.sa6.sin6_port = htons(port); +@@ -1348,8 +1343,9 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) + } + + rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa6)); +- } ++ break; + #endif /* ENABLE_IPV6 */ ++ } + + if(got_exit_signal) { + sclose(serverfd); +@@ -1924,21 +1920,20 @@ int main(int argc, char *argv[]) + int arg=1; + long pid; + const char *hostport = "127.0.0.1"; ++ const char *socket_type = "IPv4"; ++ char port_str[11]; ++ const char *location_str = port_str; + size_t socket_idx; + + memset(&req, 0, sizeof(req)); + + while(argc>arg) { + if(!strcmp("--version", argv[arg])) { +- printf("sws IPv4%s" +- "\n" +- , ++ puts("sws IPv4" + #ifdef ENABLE_IPV6 + "/IPv6" +-#else +- "" + #endif +- ); ++ ); + return 0; + } + else if(!strcmp("--pidfile", argv[arg])) { +@@ -1957,16 +1952,16 @@ int main(int argc, char *argv[]) + end_of_headers = "\r\n"; /* gopher style is much simpler */ + } + else if(!strcmp("--ipv4", argv[arg])) { +-#ifdef ENABLE_IPV6 +- ipv_inuse = "IPv4"; +- use_ipv6 = FALSE; +-#endif ++ socket_type = "IPv4"; ++ socket_domain = AF_INET; ++ location_str = port_str; + arg++; + } + else if(!strcmp("--ipv6", argv[arg])) { + #ifdef ENABLE_IPV6 +- ipv_inuse = "IPv6"; +- use_ipv6 = TRUE; ++ socket_type = "IPv6"; ++ socket_domain = AF_INET6; ++ location_str = port_str; + #endif + arg++; + } +@@ -2018,6 +2013,8 @@ int main(int argc, char *argv[]) + } + } + ++ snprintf(port_str, sizeof(port_str), "port %hu", port); ++ + #ifdef WIN32 + win32_init(); + atexit(win32_cleanup); +@@ -2027,14 +2024,7 @@ int main(int argc, char *argv[]) + + pid = (long)getpid(); + +-#ifdef ENABLE_IPV6 +- if(!use_ipv6) +-#endif +- sock = socket(AF_INET, SOCK_STREAM, 0); +-#ifdef ENABLE_IPV6 +- else +- sock = socket(AF_INET6, SOCK_STREAM, 0); +-#endif ++ sock = socket(socket_domain, SOCK_STREAM, 0); + + all_sockets[0] = sock; + num_sockets = 1; +@@ -2061,33 +2051,33 @@ int main(int argc, char *argv[]) + goto sws_cleanup; + } + +-#ifdef ENABLE_IPV6 +- if(!use_ipv6) { +-#endif ++ switch(socket_domain) { ++ case AF_INET: + memset(&me.sa4, 0, sizeof(me.sa4)); + me.sa4.sin_family = AF_INET; + me.sa4.sin_addr.s_addr = INADDR_ANY; + me.sa4.sin_port = htons(port); + rc = bind(sock, &me.sa, sizeof(me.sa4)); ++ break; + #ifdef ENABLE_IPV6 +- } +- else { ++ case AF_INET6: + memset(&me.sa6, 0, sizeof(me.sa6)); + me.sa6.sin6_family = AF_INET6; + me.sa6.sin6_addr = in6addr_any; + me.sa6.sin6_port = htons(port); + rc = bind(sock, &me.sa, sizeof(me.sa6)); +- } ++ break; + #endif /* ENABLE_IPV6 */ ++ } + if(0 != rc) { + error = SOCKERRNO; +- logmsg("Error binding socket on port %hu: (%d) %s", +- port, error, strerror(error)); ++ logmsg("Error binding socket on %s: (%d) %s", ++ location_str, error, strerror(error)); + goto sws_cleanup; + } + +- logmsg("Running %s %s version on port %d", +- use_gopher?"GOPHER":"HTTP", ipv_inuse, (int)port); ++ logmsg("Running %s %s version on %s", ++ use_gopher?"GOPHER":"HTTP", socket_type, location_str); + + /* start accepting connections */ + rc = listen(sock, 5); +@@ -2251,8 +2241,8 @@ sws_cleanup: + restore_signal_handlers(); + + if(got_exit_signal) { +- logmsg("========> %s sws (port: %d pid: %ld) exits with signal (%d)", +- ipv_inuse, (int)port, pid, exit_signal); ++ logmsg("========> %s sws (%s pid: %ld) exits with signal (%d)", ++ socket_type, location_str, pid, exit_signal); + /* + * To properly set the return status of the process we + * must raise the same signal SIGINT or SIGTERM that we +-- +2.5.2 + + +From d8d875f7c528157feec0795c03bd065420903f5d Mon Sep 17 00:00:00 2001 +From: Steve Holme +Date: Wed, 3 Dec 2014 00:00:40 +0000 +Subject: [PATCH 02/11] sws.c: Fixed compilation warning when IPv6 is disabled + +sws.c:69: warning: comma at end of enumerator list + +Upstream-commit: d784000a1468efc986c7d156d2e7c84d1920af87 +Signed-off-by: Kamil Dudka +--- + tests/server/sws.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/server/sws.c b/tests/server/sws.c +index fa10d54..2b7e628 100644 +--- a/tests/server/sws.c ++++ b/tests/server/sws.c +@@ -66,9 +66,9 @@ + #endif + + static enum { +- socket_domain_inet = AF_INET, ++ socket_domain_inet = AF_INET + #ifdef ENABLE_IPV6 +- socket_domain_inet6 = AF_INET6 ++ , socket_domain_inet6 = AF_INET6 + #endif + } socket_domain = AF_INET; + static bool use_gopher = FALSE; +-- +2.5.2 + + +From db2095dec37630309bacca6795cd4cfcf6557c9b Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Thu, 27 Nov 2014 23:59:20 +0100 +Subject: [PATCH 03/11] sws: restrict TCP_NODELAY to IP sockets + +TCP_NODELAY does not make sense for Unix sockets, so enable it only if +the socket is using IP. + +Signed-off-by: Peter Wu + +Upstream-commit: fb7d7e0022f22035449bbc506068004f0568f8ae +Signed-off-by: Kamil Dudka +--- + tests/server/sws.c | 73 ++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 44 insertions(+), 29 deletions(-) + +diff --git a/tests/server/sws.c b/tests/server/sws.c +index 2b7e628..0739a70 100644 +--- a/tests/server/sws.c ++++ b/tests/server/sws.c +@@ -331,6 +331,21 @@ static void restore_signal_handlers(void) + #endif + } + ++/* returns true if the current socket is an IP one */ ++static bool socket_domain_is_ip(void) ++{ ++ switch(socket_domain) { ++ case AF_INET: ++#ifdef ENABLE_IPV6 ++ case AF_INET6: ++#endif ++ return true; ++ default: ++ /* case AF_UNIX: */ ++ return false; ++ } ++} ++ + /* based on the testno, parse the correct server commands */ + static int parse_servercmd(struct httprequest *req) + { +@@ -1282,9 +1297,6 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) + int rc; + const char *op_br = ""; + const char *cl_br = ""; +-#ifdef TCP_NODELAY +- curl_socklen_t flag; +-#endif + + #ifdef ENABLE_IPV6 + if(socket_domain == AF_INET6) { +@@ -1309,13 +1321,15 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) + } + + #ifdef TCP_NODELAY +- /* Disable the Nagle algorithm */ +- flag = 1; +- if(0 != setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, +- (void *)&flag, sizeof(flag))) +- logmsg("====> TCP_NODELAY for server conection failed"); +- else +- logmsg("TCP_NODELAY set for server conection"); ++ if(socket_domain_is_ip()) { ++ /* Disable the Nagle algorithm */ ++ curl_socklen_t flag = 1; ++ if(0 != setsockopt(serverfd, IPPROTO_TCP, TCP_NODELAY, ++ (void *)&flag, sizeof(flag))) ++ logmsg("====> TCP_NODELAY for server conection failed"); ++ else ++ logmsg("TCP_NODELAY set for server conection"); ++ } + #endif + + switch(socket_domain) { +@@ -1398,9 +1412,6 @@ static void http_connect(curl_socket_t *infdp, + bool poll_server_rd[2] = { TRUE, TRUE }; + bool poll_client_wr[2] = { TRUE, TRUE }; + bool poll_server_wr[2] = { TRUE, TRUE }; +-#ifdef TCP_NODELAY +- curl_socklen_t flag; +-#endif + bool primary = FALSE; + bool secondary = FALSE; + int max_tunnel_idx; /* CTRL or DATA */ +@@ -1514,13 +1525,15 @@ static void http_connect(curl_socket_t *infdp, + memset(&req2, 0, sizeof(req2)); + logmsg("====> Client connect DATA"); + #ifdef TCP_NODELAY +- /* Disable the Nagle algorithm */ +- flag = 1; +- if(0 != setsockopt(datafd, IPPROTO_TCP, TCP_NODELAY, +- (void *)&flag, sizeof(flag))) +- logmsg("====> TCP_NODELAY for client DATA conection failed"); +- else +- logmsg("TCP_NODELAY set for client DATA conection"); ++ if(socket_domain_is_ip()) { ++ /* Disable the Nagle algorithm */ ++ curl_socklen_t flag = 1; ++ if(0 != setsockopt(datafd, IPPROTO_TCP, TCP_NODELAY, ++ (void *)&flag, sizeof(flag))) ++ logmsg("====> TCP_NODELAY for client DATA conection failed"); ++ else ++ logmsg("TCP_NODELAY set for client DATA conection"); ++ } + #endif + req2.pipelining = FALSE; + init_httprequest(&req2); +@@ -1826,15 +1839,17 @@ static curl_socket_t accept_connection(curl_socket_t sock) + num_sockets += 1; + + #ifdef TCP_NODELAY +- /* +- * Disable the Nagle algorithm to make it easier to send out a large +- * response in many small segments to torture the clients more. +- */ +- if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY, +- (void *)&flag, sizeof(flag))) +- logmsg("====> TCP_NODELAY failed"); +- else +- logmsg("TCP_NODELAY set"); ++ if(socket_domain_is_ip()) { ++ /* ++ * Disable the Nagle algorithm to make it easier to send out a large ++ * response in many small segments to torture the clients more. ++ */ ++ if(0 != setsockopt(msgsock, IPPROTO_TCP, TCP_NODELAY, ++ (void *)&flag, sizeof(flag))) ++ logmsg("====> TCP_NODELAY failed"); ++ else ++ logmsg("TCP_NODELAY set"); ++ } + #endif + + return msgsock; +-- +2.5.2 + + +From 7ab987459a931e593dc9f533d6e6cb6e9a26d424 Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Wed, 3 Dec 2014 02:20:00 +0100 +Subject: [PATCH 04/11] sws: add UNIX domain socket support + +This extends sws with a --unix-socket option which causes the port to +be ignored (as the server now listens on the path specified by +--unix-socket). This feature will be available in the following patch +that enables checking for UNIX domain socket support. + +Proxy support (CONNECT) is not considered nor tested. It does not make +sense anyway, first connecting through a TCP proxy, then let that TCP +proxy connect to a UNIX socket. + +Signed-off-by: Peter Wu + +Upstream-commit: e9c7a86220ddf4e67b8bff56cddfc7388afcc9ef +Signed-off-by: Kamil Dudka +--- + tests/server/server_sockaddr.h | 9 ++++++- + tests/server/sws.c | 53 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 61 insertions(+), 1 deletion(-) + +diff --git a/tests/server/server_sockaddr.h b/tests/server/server_sockaddr.h +index 6a17fe0..3f4cd67 100644 +--- a/tests/server/server_sockaddr.h ++++ b/tests/server/server_sockaddr.h +@@ -7,7 +7,7 @@ + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * +- * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. ++ * 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 +@@ -23,12 +23,19 @@ + ***************************************************************************/ + #include "server_setup.h" + ++#ifdef HAVE_SYS_UN_H ++#include /* for sockaddr_un */ ++#endif ++ + typedef union { + struct sockaddr sa; + struct sockaddr_in sa4; + #ifdef ENABLE_IPV6 + struct sockaddr_in6 sa6; + #endif ++#ifdef USE_UNIX_SOCKETS ++ struct sockaddr_un sau; ++#endif + } srvr_sockaddr_union_t; + + #endif /* HEADER_CURL_SERVER_SOCKADDR_H */ +diff --git a/tests/server/sws.c b/tests/server/sws.c +index 0739a70..24ecb8f 100644 +--- a/tests/server/sws.c ++++ b/tests/server/sws.c +@@ -70,6 +70,9 @@ static enum { + #ifdef ENABLE_IPV6 + , socket_domain_inet6 = AF_INET6 + #endif ++#ifdef USE_UNIX_SOCKETS ++ , socket_domain_unix = AF_UNIX ++#endif + } socket_domain = AF_INET; + static bool use_gopher = FALSE; + static int serverlogslocked = 0; +@@ -1359,6 +1362,11 @@ static curl_socket_t connect_to(const char *ipaddr, unsigned short port) + rc = connect(serverfd, &serveraddr.sa, sizeof(serveraddr.sa6)); + break; + #endif /* ENABLE_IPV6 */ ++#ifdef USE_UNIX_SOCKETS ++ case AF_UNIX: ++ logmsg("Proxying through UNIX socket is not (yet?) supported."); ++ return CURL_SOCKET_BAD; ++#endif /* USE_UNIX_SOCKETS */ + } + + if(got_exit_signal) { +@@ -1928,6 +1936,10 @@ int main(int argc, char *argv[]) + int wrotepidfile = 0; + int flag; + unsigned short port = DEFAULT_PORT; ++#ifdef USE_UNIX_SOCKETS ++ const char *unix_socket = NULL; ++ bool unlink_socket = false; ++#endif + char *pidname= (char *)".http.pid"; + struct httprequest req; + int rc; +@@ -1948,6 +1960,9 @@ int main(int argc, char *argv[]) + #ifdef ENABLE_IPV6 + "/IPv6" + #endif ++#ifdef USE_UNIX_SOCKETS ++ "/unix" ++#endif + ); + return 0; + } +@@ -1980,6 +1995,23 @@ int main(int argc, char *argv[]) + #endif + arg++; + } ++ else if(!strcmp("--unix-socket", argv[arg])) { ++ arg++; ++ if(argc>arg) { ++#ifdef USE_UNIX_SOCKETS ++ unix_socket = argv[arg]; ++ if(strlen(unix_socket) >= sizeof(me.sau.sun_path)) { ++ fprintf(stderr, "sws: socket path must be shorter than %zu chars\n", ++ sizeof(me.sau.sun_path)); ++ return 0; ++ } ++ socket_type = "unix"; ++ socket_domain = AF_UNIX; ++ location_str = unix_socket; ++#endif ++ arg++; ++ } ++ } + else if(!strcmp("--port", argv[arg])) { + arg++; + if(argc>arg) { +@@ -2020,6 +2052,7 @@ int main(int argc, char *argv[]) + " --pidfile [file]\n" + " --ipv4\n" + " --ipv6\n" ++ " --unix-socket [file]\n" + " --port [port]\n" + " --srcdir [path]\n" + " --connect [ip4-addr]\n" +@@ -2083,6 +2116,14 @@ int main(int argc, char *argv[]) + rc = bind(sock, &me.sa, sizeof(me.sa6)); + break; + #endif /* ENABLE_IPV6 */ ++#ifdef USE_UNIX_SOCKETS ++ case AF_UNIX: ++ memset(&me.sau, 0, sizeof(me.sau)); ++ me.sau.sun_family = AF_UNIX; ++ strncpy(me.sau.sun_path, unix_socket, sizeof(me.sau.sun_path)); ++ rc = bind(sock, &me.sa, sizeof(me.sau)); ++ break; ++#endif /* USE_UNIX_SOCKETS */ + } + if(0 != rc) { + error = SOCKERRNO; +@@ -2103,6 +2144,11 @@ int main(int argc, char *argv[]) + goto sws_cleanup; + } + ++#ifdef USE_UNIX_SOCKETS ++ /* listen succeeds, so let's assume a valid listening UNIX socket */ ++ unlink_socket = true; ++#endif ++ + /* + ** As soon as this server writes its pid file the test harness will + ** attempt to connect to this server and initiate its verification. +@@ -2242,6 +2288,13 @@ sws_cleanup: + if(sock != CURL_SOCKET_BAD) + sclose(sock); + ++#ifdef USE_UNIX_SOCKETS ++ if(unlink_socket && socket_domain == AF_UNIX) { ++ rc = unlink(unix_socket); ++ logmsg("unlink(%s) = %d (%s)", unix_socket, rc, strerror(rc)); ++ } ++#endif ++ + if(got_exit_signal) + logmsg("signalled to die"); + +-- +2.5.2 + + +From d04ea6f7f09e1556f80c4bbf4fc9497f83bc37a6 Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Thu, 27 Nov 2014 23:59:23 +0100 +Subject: [PATCH 05/11] tests: add HTTP UNIX socket server testing support + +The variable `$ipvnum` can now contain "unix" besides the integers 4 +and 6 since the variable. Functions which receive this parameter +have their `$port` parameter renamed to `$port_or_path` to support a +path to the UNIX domain socket (as a "port" is only meaningful for TCP). + +Signed-off-by: Peter Wu + +Upstream-commit: f1cc2a2c0cf8e191e606c6093c679fbee95e8809 +Signed-off-by: Kamil Dudka +--- + tests/FILEFORMAT | 2 ++ + tests/README | 3 ++ + tests/httpserver.pl | 15 ++++++++- + tests/runtests.pl | 96 +++++++++++++++++++++++++++++++++++++++++++++-------- + tests/serverhelp.pm | 4 +-- + 5 files changed, 104 insertions(+), 16 deletions(-) + +diff --git a/tests/FILEFORMAT b/tests/FILEFORMAT +index 96cd5c8..702368f 100644 +--- a/tests/FILEFORMAT ++++ b/tests/FILEFORMAT +@@ -165,6 +165,7 @@ smtp + httptls+srp + httptls+srp-ipv6 + http-proxy ++http-unix + + Give only one per line. This subsection is mandatory. + +@@ -284,6 +285,7 @@ Available substitute variables include: + %HTTPPORT - Port number of the HTTP server + %HOST6IP - IPv6 address of the host running this test + %HTTP6PORT - IPv6 port number of the HTTP server ++%HTTPUNIXPATH - Path to the UNIX socket of the HTTP server + %HTTPSPORT - Port number of the HTTPS server + %PROXYPORT - Port number of the HTTP proxy + %FTPPORT - Port number of the FTP server +diff --git a/tests/README b/tests/README +index fff618e..b442693 100644 +--- a/tests/README ++++ b/tests/README +@@ -80,6 +80,9 @@ The cURL Test Suite + machine, or just move the servers in case you have local services on any of + those ports. + ++ The HTTP server supports listening on a UNIX domain socket, the default ++ location is 'http.sock'. ++ + 1.4 Run + + 'make test'. This builds the test suite support code and invokes the +diff --git a/tests/httpserver.pl b/tests/httpserver.pl +index a38c3ce..1b8c3d2 100755 +--- a/tests/httpserver.pl ++++ b/tests/httpserver.pl +@@ -36,6 +36,7 @@ use serverhelp qw( + + my $verbose = 0; # set to 1 for debugging + my $port = 8990; # just a default ++my $unix_socket; # location to place a listening UNIX socket + my $ipvnum = 4; # default IP version of http server + my $idnum = 1; # dafault http server instance number + my $proto = 'http'; # protocol the http server speaks +@@ -74,6 +75,13 @@ while(@ARGV) { + elsif($ARGV[0] eq '--ipv6') { + $ipvnum = 6; + } ++ elsif($ARGV[0] eq '--unix-socket') { ++ $ipvnum = 'unix'; ++ if($ARGV[1]) { ++ $unix_socket = $ARGV[1]; ++ shift @ARGV; ++ } ++ } + elsif($ARGV[0] eq '--gopher') { + $gopher = 1; + } +@@ -117,7 +125,12 @@ if(!$logfile) { + $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; + $flags .= "--gopher " if($gopher); + $flags .= "--connect $connect " if($connect); +-$flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\""; ++if($ipvnum eq 'unix') { ++ $flags .= "--unix-socket '$unix_socket' "; ++} else { ++ $flags .= "--ipv$ipvnum --port $port "; ++} ++$flags .= "--srcdir \"$srcdir\""; + + if($verbose) { + print STDERR "RUN: server/sws $flags\n"; +diff --git a/tests/runtests.pl b/tests/runtests.pl +index b39da66..fa96345 100755 +--- a/tests/runtests.pl ++++ b/tests/runtests.pl +@@ -140,6 +140,7 @@ my $GOPHER6PORT; # Gopher IPv6 server port + my $HTTPTLSPORT; # HTTP TLS (non-stunnel) server port + my $HTTPTLS6PORT; # HTTP TLS (non-stunnel) IPv6 server port + my $HTTPPROXYPORT; # HTTP proxy port, when using CONNECT ++my $HTTPUNIXPATH; # HTTP server UNIX domain socket path + + my $srcdir = $ENV{'srcdir'} || '.'; + my $CURL="../src/curl".exe_ext(); # what curl executable to run on the tests +@@ -201,10 +202,12 @@ my $ssl_version; # set if libcurl is built with SSL support + my $large_file; # set if libcurl is built with large file support + my $has_idn; # set if libcurl is built with IDN support + my $http_ipv6; # set if HTTP server has IPv6 support ++my $http_unix; # set if HTTP server has UNIX sockets support + my $ftp_ipv6; # set if FTP server has IPv6 support + my $tftp_ipv6; # set if TFTP server has IPv6 support + my $gopher_ipv6; # set if Gopher server has IPv6 support + my $has_ipv6; # set if libcurl is built with IPv6 support ++my $has_unix; # set if libcurl is built with UNIX sockets support + my $has_libz; # set if libcurl is built with libz support + my $has_getrlimit; # set if system has getrlimit() + my $has_ntlm; # set if libcurl is built with NTLM support +@@ -358,6 +361,13 @@ sub init_serverpidfile_hash { + } + } + } ++ for my $proto (('http', 'imap', 'pop3', 'smtp')) { ++ for my $ssl (('', 's')) { ++ my $serv = servername_id("$proto$ssl", "unix", 1); ++ my $pidf = server_pidfilename("$proto$ssl", "unix", 1); ++ $serverpidfile{$serv} = $pidf; ++ } ++ } + } + + ####################################################################### +@@ -641,11 +651,11 @@ sub stopserver { + # All servers relative to the given one must be stopped also + # + my @killservers; +- if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|))$/) { ++ if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) { + # given a stunnel based ssl server, also kill non-ssl underlying one + push @killservers, "${1}${2}"; + } +- elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|))$/) { ++ elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|-unix|))$/) { + # given a non-ssl server, also kill stunnel based ssl piggybacking one + push @killservers, "${1}s${2}"; + } +@@ -691,10 +701,12 @@ sub stopserver { + # assign requested address") + # + sub verifyhttp { +- my ($proto, $ipvnum, $idnum, $ip, $port) = @_; ++ my ($proto, $ipvnum, $idnum, $ip, $port_or_path) = @_; + my $server = servername_id($proto, $ipvnum, $idnum); + my $pid = 0; + my $bonus=""; ++ # $port_or_path contains a path for UNIX sockets, sws ignores the port ++ my $port = ($ipvnum eq "unix") ? 80 : $port_or_path; + + my $verifyout = "$LOGDIR/". + servername_canon($proto, $ipvnum, $idnum) .'_verify.out'; +@@ -714,6 +726,7 @@ sub verifyhttp { + $flags .= "--silent "; + $flags .= "--verbose "; + $flags .= "--globoff "; ++ $flags .= "--unix-socket '$port_or_path' " if $ipvnum eq "unix"; + $flags .= "-1 " if($has_axtls); + $flags .= "--insecure " if($proto eq 'https'); + $flags .= "\"$proto://$ip:$port/${bonus}verifiedserver\""; +@@ -1160,7 +1173,7 @@ sub responsiveserver { + # start the http server + # + sub runhttpserver { +- my ($proto, $verbose, $alt, $port) = @_; ++ my ($proto, $verbose, $alt, $port_or_path) = @_; + my $ip = $HOSTIP; + my $ipvnum = 4; + my $idnum = 1; +@@ -1188,6 +1201,10 @@ sub runhttpserver { + if ($doesntrun{$pidfile}) { + return (0,0); + } ++ elsif($alt eq "unix") { ++ # IP (protocol) is mutually exclusive with UNIX sockets ++ $ipvnum = "unix"; ++ } + + my $pid = processexists($pidfile); + if($pid > 0) { +@@ -1204,7 +1221,12 @@ sub runhttpserver { + $flags .= "--verbose " if($debugprotocol); + $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; + $flags .= "--id $idnum " if($idnum > 1); +- $flags .= "--ipv$ipvnum --port $port --srcdir \"$srcdir\""; ++ if($ipvnum eq "unix") { ++ $flags .= "--unix-socket '$port_or_path' "; ++ } else { ++ $flags .= "--ipv$ipvnum --port $port_or_path "; ++ } ++ $flags .= "--srcdir \"$srcdir\""; + + my $cmd = "$perl $srcdir/httpserver.pl $flags"; + my ($httppid, $pid2) = startnew($cmd, $pidfile, 15, 0); +@@ -1219,7 +1241,7 @@ sub runhttpserver { + } + + # Server is up. Verify that we can speak to it. +- my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port); ++ my $pid3 = verifyserver($proto, $ipvnum, $idnum, $ip, $port_or_path); + if(!$pid3) { + logmsg "RUN: $srvrname server failed verification\n"; + # failed to talk to it properly. Kill the server and return failure +@@ -1984,7 +2006,7 @@ sub runsocksserver { + # be used to verify that a server present in %run hash is still functional + # + sub responsive_http_server { +- my ($proto, $verbose, $alt, $port) = @_; ++ my ($proto, $verbose, $alt, $port_or_path) = @_; + my $ip = $HOSTIP; + my $ipvnum = 4; + my $idnum = 1; +@@ -1997,8 +2019,12 @@ sub responsive_http_server { + elsif($alt eq "proxy") { + $idnum = 2; + } ++ elsif($alt eq "unix") { ++ # IP (protocol) is mutually exclusive with UNIX sockets ++ $ipvnum = "unix"; ++ } + +- return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port); ++ return &responsiveserver($proto, $ipvnum, $idnum, $ip, $port_or_path); + } + + ####################################################################### +@@ -2264,9 +2290,10 @@ sub checksystem { + @protocols = split(' ', lc($1)); + + # Generate a "proto-ipv6" version of each protocol to match the +- # IPv6 name. This works even if IPv6 support isn't ++ # IPv6 name and a "proto-unix" to match the variant which ++ # uses UNIX domain sockets. This works even if support isn't + # compiled in because the test will fail. +- push @protocols, map($_ . '-ipv6', @protocols); ++ push @protocols, map(("$_-ipv6", "$_-unix"), @protocols); + + # 'http-proxy' is used in test cases to do CONNECT through + push @protocols, 'http-proxy'; +@@ -2299,6 +2326,9 @@ sub checksystem { + if($feat =~ /IPv6/i) { + $has_ipv6 = 1; + } ++ if($feat =~ /unix-sockets/i) { ++ $has_unix = 1; ++ } + if($feat =~ /libz/i) { + $has_libz = 1; + } +@@ -2396,6 +2426,12 @@ sub checksystem { + } + } + ++ if($has_unix) { ++ # client has UNIX sockets support, check whether the HTTP server has it ++ my @sws = `server/sws --version`; ++ $http_unix = 1 if($sws[0] =~ /unix/); ++ } ++ + if(!$curl_debug && $torture) { + die "can't run torture tests since curl was not built with curldebug"; + } +@@ -2423,6 +2459,7 @@ sub checksystem { + logmsg sprintf(" track memory: %s\n", $curl_debug?"ON ":"OFF"); + logmsg sprintf("* valgrind: %8s", $valgrind?"ON ":"OFF"); + logmsg sprintf(" HTTP IPv6 %s\n", $http_ipv6?"ON ":"OFF"); ++ logmsg sprintf("* HTTP UNIX %s\n", $http_unix?"ON ":"OFF"); + logmsg sprintf("* FTP IPv6 %8s", $ftp_ipv6?"ON ":"OFF"); + logmsg sprintf(" Libtool lib: %s\n", $libtool?"ON ":"OFF"); + logmsg sprintf("* Shared build: %s\n", $has_shared); +@@ -2473,6 +2510,13 @@ sub checksystem { + logmsg "\n"; + } + ++ if($has_unix) { ++ logmsg "* UNIX socket paths:\n"; ++ if($http_unix) { ++ logmsg sprintf("* HTTP-UNIX:%s\n", $HTTPUNIXPATH); ++ } ++ } ++ + $has_textaware = ($^O eq 'MSWin32') || ($^O eq 'msys'); + + logmsg "***************************************** \n"; +@@ -2520,6 +2564,10 @@ sub subVariables { + $$thing =~ s/%TFTP6PORT/$TFTP6PORT/g; + $$thing =~ s/%TFTPPORT/$TFTPPORT/g; + ++ # server UNIX domain socket paths ++ ++ $$thing =~ s/%HTTPUNIXPATH/$HTTPUNIXPATH/g; ++ + # client IP addresses + + $$thing =~ s/%CLIENT6IP/$CLIENT6IP/g; +@@ -2707,6 +2755,11 @@ sub singletest { + next; + } + } ++ elsif($f eq "unix-sockets") { ++ if($has_unix) { ++ next; ++ } ++ } + elsif($f eq "libz") { + if($has_libz) { + next; +@@ -3219,11 +3272,11 @@ sub singletest { + my @killservers; + foreach my $server (@killtestservers) { + chomp $server; +- if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|))$/) { ++ if($server =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) { + # given a stunnel ssl server, also kill non-ssl underlying one + push @killservers, "${1}${2}"; + } +- elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|))$/) { ++ elsif($server =~ /^(ftp|http|imap|pop3|smtp)((\d*)(-ipv6|-unix|))$/) { + # given a non-ssl server, also kill stunnel piggybacking one + push @killservers, "${1}s${2}"; + } +@@ -3728,7 +3781,7 @@ sub startservers { + $what =~ s/[^a-z0-9-]//g; + + my $certfile; +- if($what =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|))$/) { ++ if($what =~ /^(ftp|http|imap|pop3|smtp)s((\d*)(-ipv6|-unix|))$/) { + $certfile = ($whatlist[1]) ? $whatlist[1] : 'stunnel.pem'; + } + +@@ -4066,6 +4119,22 @@ sub startservers { + } + } + } ++ elsif($what eq "http-unix") { ++ if($torture && $run{'http-unix'} && ++ !responsive_http_server("http", $verbose, "unix", $HTTPUNIXPATH)) { ++ stopserver('http-unix'); ++ } ++ if(!$run{'http-unix'}) { ++ ($pid, $pid2) = runhttpserver("http", $verbose, "unix", ++ $HTTPUNIXPATH); ++ if($pid <= 0) { ++ return "failed starting HTTP-unix server"; ++ } ++ logmsg sprintf("* pid http-unix => %d %d\n", $pid, $pid2) ++ if($verbose); ++ $run{'http-unix'}="$pid $pid2"; ++ } ++ } + elsif($what eq "none") { + logmsg "* starts no server\n" if ($verbose); + } +@@ -4502,6 +4571,7 @@ $GOPHER6PORT = $base++; # Gopher IPv6 server port + $HTTPTLSPORT = $base++; # HTTP TLS (non-stunnel) server port + $HTTPTLS6PORT = $base++; # HTTP TLS (non-stunnel) IPv6 server port + $HTTPPROXYPORT = $base++; # HTTP proxy port, when using CONNECT ++$HTTPUNIXPATH = 'http.sock'; # HTTP server UNIX domain socket path + + ####################################################################### + # clear and create logging directory: +diff --git a/tests/serverhelp.pm b/tests/serverhelp.pm +index a1d1dc3..1fc621b 100644 +--- a/tests/serverhelp.pm ++++ b/tests/serverhelp.pm +@@ -109,8 +109,8 @@ sub servername_str { + + $ipver = (not $ipver) ? 'ipv4' : lc($ipver); + die "unsupported IP version: '$ipver'" unless($ipver && +- ($ipver =~ /^(4|6|ipv4|ipv6|-ipv4|-ipv6)$/)); +- $ipver = ($ipver =~ /6$/) ? '-IPv6' : ''; ++ ($ipver =~ /^(4|6|ipv4|ipv6|-ipv4|-ipv6|unix)$/)); ++ $ipver = ($ipver =~ /6$/) ? '-IPv6' : (($ipver =~ /unix$/) ? '-unix' : ''); + + $idnum = 1 if(not $idnum); + die "unsupported ID number: '$idnum'" unless($idnum && +-- +2.5.2 + + +From d2f7b1d51e356586356da87d1ae32c0c44274887 Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Thu, 27 Nov 2014 23:59:24 +0100 +Subject: [PATCH 06/11] tests: add two HTTP over UNIX socket tests + +test1435: a simple test that checks whether a HTTP request can be +performed over the UNIX socket. The hostname/port are interpreted +by sws and should be ignored by cURL. + +test1436: test for the ability to do two requests to the same host, +interleaved with one to a different hostname. + +Signed-off-by: Peter Wu + +Upstream-commit: 479abdd32eee15dab78d0cd6b1786d569680f0ac +Signed-off-by: Kamil Dudka +--- + tests/data/Makefile.am | 1 + + tests/data/Makefile.in | 1 + + tests/data/test1435 | 46 +++++++++++++++++++++++++++ + tests/data/test1436 | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 133 insertions(+) + create mode 100644 tests/data/test1435 + create mode 100644 tests/data/test1436 + +diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am +index c4f76df..35bc6eb 100644 +--- a/tests/data/Makefile.am ++++ b/tests/data/Makefile.am +@@ -93,6 +93,7 @@ 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 test1415 \ ++test1435 test1436 \ + test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ + test1508 test1529 \ + test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \ +diff --git a/tests/data/Makefile.in b/tests/data/Makefile.in +index e73ca96..d5e5f01 100644 +--- a/tests/data/Makefile.in ++++ b/tests/data/Makefile.in +@@ -357,6 +357,7 @@ 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 test1415 \ ++test1435 test1436 \ + test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \ + test1508 test1529 \ + test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \ +diff --git a/tests/data/test1435 b/tests/data/test1435 +new file mode 100644 +index 0000000..56ff9d1 +--- /dev/null ++++ b/tests/data/test1435 +@@ -0,0 +1,46 @@ ++ ++ ++ ++HTTP ++HTTP GET ++unix sockets ++ ++ ++ ++ ++ ++HTTP/1.1 200 OK ++Date: Sun, 16 Nov 2014 23:47:38 GMT ++Content-Length: 17 ++ ++Based on test300 ++ ++ ++ ++ ++ ++unix-sockets ++ ++ ++http-unix ++ ++ ++simple HTTP GET over UNIX socket ++ ++ ++--unix-socket %HTTPUNIXPATH http://server-interpreted.example.com/1435 ++ ++ ++ ++ ++ ++^User-Agent:.* ++ ++ ++GET /1435 HTTP/1.1 ++Host: server-interpreted.example.com ++Accept: */* ++ ++ ++ ++ +diff --git a/tests/data/test1436 b/tests/data/test1436 +new file mode 100644 +index 0000000..b16eadd +--- /dev/null ++++ b/tests/data/test1436 +@@ -0,0 +1,85 @@ ++ ++ ++ ++HTTP ++HTTP GET ++unix sockets ++ ++ ++ ++ ++ ++HTTP/1.1 200 OK ++Date: Mon, 17 Nov 2014 13:42:47 GMT ++Content-Length: 6 ++ ++First ++ ++ ++HTTP/1.1 200 OK ++Date: Mon, 17 Nov 2014 13:42:48 GMT ++Content-Length: 7 ++ ++Second ++ ++ ++HTTP/1.1 200 OK ++Date: Mon, 17 Nov 2014 13:42:49 GMT ++Content-Length: 6 ++ ++Third ++ ++ ++ ++ ++ ++unix-sockets ++ ++ ++http-unix ++ ++ ++HTTP requests with multiple connections over UNIX socket ++ ++ ++--unix-socket %HTTPUNIXPATH http://one.example.com/14360001 http://two.example.com/14360002 http://one.example.com/14360003 ++ ++ ++ ++ ++ ++^User-Agent:.* ++ ++ ++GET /14360001 HTTP/1.1 ++Host: one.example.com ++Accept: */* ++ ++GET /14360002 HTTP/1.1 ++Host: two.example.com ++Accept: */* ++ ++GET /14360003 HTTP/1.1 ++Host: one.example.com ++Accept: */* ++ ++ ++ ++HTTP/1.1 200 OK ++Date: Mon, 17 Nov 2014 13:42:47 GMT ++Content-Length: 6 ++ ++First ++HTTP/1.1 200 OK ++Date: Mon, 17 Nov 2014 13:42:48 GMT ++Content-Length: 7 ++ ++Second ++HTTP/1.1 200 OK ++Date: Mon, 17 Nov 2014 13:42:49 GMT ++Content-Length: 6 ++ ++Third ++ ++ ++ +-- +2.5.2 + + +From f784b2d3d6cf08193662a23aae9305f11c4a4559 Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Thu, 27 Nov 2014 23:59:25 +0100 +Subject: [PATCH 07/11] libcurl: add UNIX domain sockets support + +The ability to do HTTP requests over a UNIX domain socket has been +requested before, in Apr 2008 [0][1] and Sep 2010 [2]. While a +discussion happened, no patch seems to get through. I decided to give it +a go since I need to test a nginx HTTP server which listens on a UNIX +domain socket. + +One patch [3] seems to make it possible to use the +CURLOPT_OPENSOCKETFUNCTION function to gain a UNIX domain socket. +Another person wrote a Go program which can do HTTP over a UNIX socket +for Docker[4] which uses a special URL scheme (though the name contains +cURL, it has no relation to the cURL library). + +This patch considers support for UNIX domain sockets at the same level +as HTTP proxies / IPv6, it acts as an intermediate socket provider and +not as a separate protocol. Since this feature affects network +operations, a new feature flag was added ("unix-sockets") with a +corresponding CURL_VERSION_UNIX_SOCKETS macro. + +A new CURLOPT_UNIX_SOCKET_PATH option is added and documented. This +option enables UNIX domain sockets support for all requests on the +handle (replacing IP sockets and skipping proxies). + +A new configure option (--enable-unix-sockets) and CMake option +(ENABLE_UNIX_SOCKETS) can disable this optional feature. Note that I +deliberately did not mark this feature as advanced, this is a +feature/component that should easily be available. + + [0]: http://curl.haxx.se/mail/lib-2008-04/0279.html + [1]: http://daniel.haxx.se/blog/2008/04/14/http-over-unix-domain-sockets/ + [2]: http://sourceforge.net/p/curl/feature-requests/53/ + [3]: http://curl.haxx.se/mail/lib-2008-04/0361.html + [4]: https://github.com/Soulou/curl-unix-socket + +Signed-off-by: Peter Wu + +Upstream-commit: 970c22f970f0172e6a4c98ccc3176c740ddaa1c6 +Signed-off-by: Kamil Dudka +--- + configure | 112 +++++++++++++++++++++++++++++++++++++++ + configure.ac | 38 +++++++++++++ + docs/libcurl/curl_easy_setopt.3 | 12 +++++ + docs/libcurl/curl_version_info.3 | 2 + + docs/libcurl/symbols-in-versions | 2 + + include/curl/curl.h | 4 ++ + lib/Makefile.in | 1 + + lib/curl_addrinfo.c | 39 ++++++++++++++ + lib/curl_addrinfo.h | 4 ++ + lib/curl_config.h.in | 3 ++ + lib/url.c | 44 +++++++++++++++ + lib/urldata.h | 4 ++ + lib/version.c | 3 ++ + src/Makefile.in | 1 + + src/tool_getparam.c | 3 +- + tests/server/Makefile.in | 1 + + 16 files changed, 272 insertions(+), 1 deletion(-) + +diff --git a/configure b/configure +index c5d1817..3e1f5d3 100755 +--- a/configure ++++ b/configure +@@ -889,6 +889,7 @@ SONAME_BUMP_TRUE + CFLAG_CURL_SYMBOL_HIDING + DOING_CURL_SYMBOL_HIDING_FALSE + DOING_CURL_SYMBOL_HIDING_TRUE ++USE_UNIX_SOCKETS + BUILD_LIBHOSTNAME_FALSE + BUILD_LIBHOSTNAME_TRUE + USE_EMBEDDED_ARES_FALSE +@@ -1159,6 +1160,7 @@ enable_sspi + enable_crypto_auth + enable_ntlm_wb + enable_tls_srp ++enable_unix_sockets + enable_cookies + enable_soname_bump + ' +@@ -1873,6 +1875,8 @@ Optional Features: + helper + --enable-tls-srp Enable TLS-SRP authentication + --disable-tls-srp Disable TLS-SRP authentication ++ --enable-unix-sockets Enable UNIX domain sockets ++ --disable-unix-sockets Disable UNIX domain sockets + --enable-cookies Enable cookies support + --disable-cookies Disable cookies support + --enable-soname-bump Enable enforced SONAME bump +@@ -2607,6 +2611,61 @@ $as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + + } # ac_fn_c_check_type ++ ++# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES ++# ---------------------------------------------------- ++# Tries to find if the field MEMBER exists in type AGGR, after including ++# INCLUDES, setting cache variable VAR accordingly. ++ac_fn_c_check_member () ++{ ++ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack ++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 ++$as_echo_n "checking for $2.$3... " >&6; } ++if eval \${$4+:} false; then : ++ $as_echo_n "(cached) " >&6 ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++$5 ++int main (void) ++{ ++static $2 ac_aggr; ++if (ac_aggr.$3) ++return 0; ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ eval "$4=yes" ++else ++ cat confdefs.h - <<_ACEOF >conftest.$ac_ext ++/* end confdefs.h. */ ++$5 ++int main (void) ++{ ++static $2 ac_aggr; ++if (sizeof ac_aggr.$3) ++return 0; ++ ; ++ return 0; ++} ++_ACEOF ++if ac_fn_c_try_compile "$LINENO"; then : ++ eval "$4=yes" ++else ++ eval "$4=no" ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ++fi ++eval ac_res=\$$4 ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 ++$as_echo "$ac_res" >&6; } ++ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno ++ ++} # ac_fn_c_check_member + cat >config.log <<_ACEOF + This file contains any messages produced by compilers while + running configure, to aid debugging if configure makes a mistake. +@@ -5447,6 +5506,7 @@ PKGADD_VENDOR="curl.haxx.se" + curl_tls_srp_msg="no (--enable-tls-srp)" + curl_res_msg="default (--enable-ares / --enable-threaded-resolver)" + curl_ipv6_msg="no (--enable-ipv6)" ++curl_unix_sockets_msg="no (--enable-unix-sockets)" + curl_idn_msg="no (--with-{libidn,winidn})" + curl_manual_msg="no (--enable-manual)" + curl_libcurl_msg="enabled (--disable-libcurl-option)" +@@ -39239,6 +39299,53 @@ $as_echo "#define USE_TLS_SRP 1" >>confdefs.h + curl_tls_srp_msg="enabled" + fi + ++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable UNIX domain sockets" >&5 ++$as_echo_n "checking whether to enable UNIX domain sockets... " >&6; } ++# Check whether --enable-unix-sockets was given. ++if test "${enable_unix_sockets+set}" = set; then : ++ enableval=$enable_unix_sockets; case "$enableval" in ++ no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 ++$as_echo "no" >&6; } ++ want_unix_sockets=no ++ ;; ++ *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 ++$as_echo "yes" >&6; } ++ want_unix_sockets=yes ++ ;; ++ esac ++else ++ ++ { $as_echo "$as_me:${as_lineno-$LINENO}: result: auto" >&5 ++$as_echo "auto" >&6; } ++ want_unix_sockets=auto ++ ++ ++fi ++ ++if test "x$want_unix_sockets" != "xno"; then ++ ac_fn_c_check_member "$LINENO" "struct sockaddr_un" "sun_path" "ac_cv_member_struct_sockaddr_un_sun_path" " ++ #include ++ ++" ++if test "x$ac_cv_member_struct_sockaddr_un_sun_path" = xyes; then : ++ ++ ++$as_echo "#define USE_UNIX_SOCKETS 1" >>confdefs.h ++ ++ USE_UNIX_SOCKETS=1 ++ ++ curl_unix_sockets_msg="enabled" ++ ++else ++ ++ if test "x$want_unix_sockets" = "xyes"; then ++ as_fn_error $? "--enable-unix-sockets is not available on this platform!" "$LINENO" 5 ++ fi ++ ++fi ++ ++fi ++ + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable support for cookies" >&5 + $as_echo_n "checking whether to enable support for cookies... " >&6; } + # Check whether --enable-cookies was given. +@@ -39357,6 +39464,9 @@ fi + if test "x$IPV6_ENABLED" = "x1"; then + SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6" + fi ++if test "x$USE_UNIX_SOCKETS" = "x1"; then ++ SUPPORT_FEATURES="$SUPPORT_FEATURES unix-sockets" ++fi + if test "x$HAVE_LIBZ" = "x1"; then + SUPPORT_FEATURES="$SUPPORT_FEATURES libz" + fi +@@ -42289,6 +42399,7 @@ _EOF + TLS-SRP support: ${curl_tls_srp_msg} + resolver: ${curl_res_msg} + ipv6 support: ${curl_ipv6_msg} ++ UNIX sockets support: ${curl_unix_sockets_msg} + IDN support: ${curl_idn_msg} + Build libcurl: Shared=${enable_shared}, Static=${enable_static} + Built-in manual: ${curl_manual_msg} +@@ -42319,6 +42430,7 @@ $as_echo "$as_me: Configured to build curl/libcurl: + TLS-SRP support: ${curl_tls_srp_msg} + resolver: ${curl_res_msg} + ipv6 support: ${curl_ipv6_msg} ++ UNIX sockets support: ${curl_unix_sockets_msg} + IDN support: ${curl_idn_msg} + Build libcurl: Shared=${enable_shared}, Static=${enable_static} + Built-in manual: ${curl_manual_msg} +diff --git a/configure.ac b/configure.ac +index 60a6b58..9612c2f 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -156,6 +156,7 @@ dnl initialize all the info variables + curl_tls_srp_msg="no (--enable-tls-srp)" + curl_res_msg="default (--enable-ares / --enable-threaded-resolver)" + curl_ipv6_msg="no (--enable-ipv6)" ++curl_unix_sockets_msg="no (--enable-unix-sockets)" + curl_idn_msg="no (--with-{libidn,winidn})" + curl_manual_msg="no (--enable-manual)" + curl_libcurl_msg="enabled (--disable-libcurl-option)" +@@ -3302,6 +3303,39 @@ if test "$want_tls_srp" = "yes" && ( test "x$HAVE_GNUTLS_SRP" = "x1" || test "x$ + fi + + dnl ************************************************************ ++dnl disable UNIX domain sockets support ++dnl ++AC_MSG_CHECKING([whether to enable UNIX domain sockets]) ++AC_ARG_ENABLE(unix-sockets, ++AC_HELP_STRING([--enable-unix-sockets],[Enable UNIX domain sockets]) ++AC_HELP_STRING([--disable-unix-sockets],[Disable UNIX domain sockets]), ++[ case "$enableval" in ++ no) AC_MSG_RESULT(no) ++ want_unix_sockets=no ++ ;; ++ *) AC_MSG_RESULT(yes) ++ want_unix_sockets=yes ++ ;; ++ esac ], [ ++ AC_MSG_RESULT(auto) ++ want_unix_sockets=auto ++ ] ++) ++if test "x$want_unix_sockets" != "xno"; then ++ AC_CHECK_MEMBER([struct sockaddr_un.sun_path], [ ++ AC_DEFINE(USE_UNIX_SOCKETS, 1, [Use UNIX domain sockets]) ++ AC_SUBST(USE_UNIX_SOCKETS, [1]) ++ curl_unix_sockets_msg="enabled" ++ ], [ ++ if test "x$want_unix_sockets" = "xyes"; then ++ AC_MSG_ERROR([--enable-unix-sockets is not available on this platform!]) ++ fi ++ ], [ ++ #include ++ ]) ++fi ++ ++dnl ************************************************************ + dnl disable cookies support + dnl + AC_MSG_CHECKING([whether to enable support for cookies]) +@@ -3382,6 +3416,9 @@ fi + if test "x$IPV6_ENABLED" = "x1"; then + SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6" + fi ++if test "x$USE_UNIX_SOCKETS" = "x1"; then ++ SUPPORT_FEATURES="$SUPPORT_FEATURES unix-sockets" ++fi + if test "x$HAVE_LIBZ" = "x1"; then + SUPPORT_FEATURES="$SUPPORT_FEATURES libz" + fi +@@ -3557,6 +3594,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl: + TLS-SRP support: ${curl_tls_srp_msg} + resolver: ${curl_res_msg} + ipv6 support: ${curl_ipv6_msg} ++ UNIX sockets support: ${curl_unix_sockets_msg} + IDN support: ${curl_idn_msg} + Build libcurl: Shared=${enable_shared}, Static=${enable_static} + Built-in manual: ${curl_manual_msg} +diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 +index d73b664..ad739e1 100644 +--- a/docs/libcurl/curl_easy_setopt.3 ++++ b/docs/libcurl/curl_easy_setopt.3 +@@ -961,6 +961,18 @@ systems support this option. (Added in 7.25.0) + Pass a long. Sets the interval, in seconds, that the operating system will wait + between sending keepalive probes. Not all operating systems support this + option. (Added in 7.25.0) ++.IP CURLOPT_UNIX_SOCKET_PATH ++Pass a \fIpath\fP to a UNIX domain socket. This enables the use of UNIX domain ++sockets as connection end point and sets the path to \fIpath\fP. If \fIpath\fP ++is NULL, then UNIX domain sockets are disabled. An empty string will result in ++an error at some point. ++ ++When enabled, cURL will connect to the UNIX domain socket instead of ++establishing a TCP connection to a host. Since no TCP connection is ++established, cURL does not need to resolve the DNS hostname in the URL. ++ ++The maximum path length on Cygwin, Linux and Solaris is 107. On other platforms ++might be even less. + .SH NAMES and PASSWORDS OPTIONS (Authentication) + .IP CURLOPT_NETRC + This parameter controls the preference of libcurl between using user names and +diff --git a/docs/libcurl/curl_version_info.3 b/docs/libcurl/curl_version_info.3 +index ccb2028..c148cbc 100644 +--- a/docs/libcurl/curl_version_info.3 ++++ b/docs/libcurl/curl_version_info.3 +@@ -133,6 +133,8 @@ libcurl was built with support for TLS-SRP. (Added in 7.21.4) + .IP CURL_VERSION_NTLM_WB + libcurl was built with support for NTLM delegation to a winbind helper. + (Added in 7.22.0) ++.IP CURL_VERSION_UNIX_SOCKETS ++libcurl was built with support for UNIX domain sockets. + .RE + \fIssl_version\fP is an ASCII string for the OpenSSL version used. If libcurl + has no SSL support, this is NULL. +diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions +index b275900..0f7469d 100644 +--- a/docs/libcurl/symbols-in-versions ++++ b/docs/libcurl/symbols-in-versions +@@ -503,6 +503,7 @@ CURLOPT_TLSAUTH_TYPE 7.21.4 + CURLOPT_TLSAUTH_USERNAME 7.21.4 + CURLOPT_TRANSFERTEXT 7.1.1 + CURLOPT_TRANSFER_ENCODING 7.21.6 ++CURLOPT_UNIX_SOCKET_PATH 7.40.0 + CURLOPT_UNRESTRICTED_AUTH 7.10.4 + CURLOPT_UPLOAD 7.1 + CURLOPT_URL 7.1 +@@ -703,6 +704,7 @@ CURL_VERSION_SPNEGO 7.10.8 + CURL_VERSION_SSL 7.10 + CURL_VERSION_SSPI 7.13.2 + CURL_VERSION_TLSAUTH_SRP 7.21.4 ++CURL_VERSION_UNIX_SOCKETS 7.40.0 + CURL_WAIT_POLLIN 7.28.0 + CURL_WAIT_POLLOUT 7.28.0 + CURL_WAIT_POLLPRI 7.28.0 +diff --git a/include/curl/curl.h b/include/curl/curl.h +index 8e548e3..14f6fd7 100644 +--- a/include/curl/curl.h ++++ b/include/curl/curl.h +@@ -1536,6 +1536,9 @@ typedef enum { + /* set the SMTP auth originator */ + CINIT(MAIL_AUTH, OBJECTPOINT, 217), + ++ /* Path to UNIX domain socket */ ++ CINIT(UNIX_SOCKET_PATH, OBJECTPOINT, 231), ++ + CURLOPT_LASTENTRY /* the last unused */ + } CURLoption; + +@@ -2154,6 +2157,7 @@ typedef struct { + #define CURL_VERSION_CURLDEBUG (1<<13) /* debug memory tracking supported */ + #define CURL_VERSION_TLSAUTH_SRP (1<<14) /* TLS-SRP auth is supported */ + #define CURL_VERSION_NTLM_WB (1<<15) /* NTLM delegating to winbind helper */ ++#define CURL_VERSION_UNIX_SOCKETS (1<<19) /* UNIX domain sockets support */ + + /* + * NAME curl_version_info() +diff --git a/lib/Makefile.in b/lib/Makefile.in +index ca02e27..5ad2600 100644 +--- a/lib/Makefile.in ++++ b/lib/Makefile.in +@@ -386,6 +386,7 @@ USE_OPENLDAP = @USE_OPENLDAP@ + USE_POLARSSL = @USE_POLARSSL@ + USE_SCHANNEL = @USE_SCHANNEL@ + USE_SSLEAY = @USE_SSLEAY@ ++USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@ + USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@ + VERSION = @VERSION@ + VERSIONED_FLAVOUR = @VERSIONED_FLAVOUR@ +diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c +index 10652c6..52e45ce 100644 +--- a/lib/curl_addrinfo.c ++++ b/lib/curl_addrinfo.c +@@ -33,6 +33,9 @@ + #ifdef HAVE_ARPA_INET_H + # include + #endif ++#ifdef HAVE_SYS_UN_H ++# include ++#endif + + #ifdef __VMS + # include +@@ -477,6 +480,42 @@ Curl_addrinfo *Curl_str2addr(char *address, int port) + return NULL; /* bad input format */ + } + ++#ifdef USE_UNIX_SOCKETS ++/** ++ * Given a path to a UNIX domain socket, return a newly allocated Curl_addrinfo ++ * struct initialized with this path. ++ */ ++Curl_addrinfo *Curl_unix2addr(const char *path) ++{ ++ Curl_addrinfo *ai; ++ struct sockaddr_un *sun; ++ size_t path_len; ++ ++ ai = calloc(1, sizeof(Curl_addrinfo)); ++ if(!ai) ++ return NULL; ++ if((ai->ai_addr = calloc(1, sizeof(struct sockaddr_un))) == NULL) { ++ free(ai); ++ return NULL; ++ } ++ /* sun_path must be able to store the NUL-terminated path */ ++ path_len = strlen(path); ++ if(path_len >= sizeof(sun->sun_path)) { ++ free(ai->ai_addr); ++ free(ai); ++ return NULL; ++ } ++ ++ ai->ai_family = AF_UNIX; ++ ai->ai_socktype = SOCK_STREAM; /* assume reliable transport for HTTP */ ++ ai->ai_addrlen = (curl_socklen_t) sizeof(struct sockaddr_un); ++ sun = (void *) ai->ai_addr; ++ sun->sun_family = AF_UNIX; ++ memcpy(sun->sun_path, path, path_len + 1); /* copy NUL byte */ ++ return ai; ++} ++#endif ++ + #if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) + /* + * curl_dofreeaddrinfo() +diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h +index 6d2b753..4ef8827 100644 +--- a/lib/curl_addrinfo.h ++++ b/lib/curl_addrinfo.h +@@ -79,6 +79,10 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); + + Curl_addrinfo *Curl_str2addr(char *dotted, int port); + ++#ifdef USE_UNIX_SOCKETS ++Curl_addrinfo *Curl_unix2addr(const char *path); ++#endif ++ + #if defined(CURLDEBUG) && defined(HAVE_FREEADDRINFO) + void + curl_dofreeaddrinfo(struct addrinfo *freethis, +diff --git a/lib/curl_config.h.in b/lib/curl_config.h.in +index 1716c96..19b66fa 100644 +--- a/lib/curl_config.h.in ++++ b/lib/curl_config.h.in +@@ -1017,6 +1017,9 @@ + /* Use TLS-SRP authentication */ + #undef USE_TLS_SRP + ++/* Use UNIX domain sockets */ ++#undef USE_UNIX_SOCKETS ++ + /* Define to 1 if you have the `normaliz' (WinIDN) library (-lnormaliz). */ + #undef USE_WIN32_IDN + +diff --git a/lib/url.c b/lib/url.c +index 57944e4..7257b5e 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -47,6 +47,10 @@ + #include + #endif + ++#ifdef HAVE_SYS_UN_H ++#include ++#endif ++ + #ifndef HAVE_SOCKET + #error "We can't compile without socket() support!" + #endif +@@ -2429,6 +2433,13 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, + data->set.tcp_keepintvl = va_arg(param, long); + break; + ++#ifdef USE_UNIX_SOCKETS ++ case CURLOPT_UNIX_SOCKET_PATH: ++ result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], ++ va_arg(param, char *)); ++ break; ++#endif ++ + default: + /* unknown tag and its companion, just ignore: */ + result = CURLE_UNKNOWN_OPTION; +@@ -4764,6 +4775,32 @@ static CURLcode resolve_server(struct SessionHandle *data, + /* set a pointer to the hostname we display */ + fix_hostname(data, conn, &conn->host); + ++#ifdef USE_UNIX_SOCKETS ++ if(data->set.str[STRING_UNIX_SOCKET_PATH]) { ++ /* UNIX domain sockets are local. The host gets ignored, just use the ++ * specified domain socket address. Do not cache "DNS entries". There is ++ * no DNS involved and we already have the filesystem path available */ ++ const char *path = data->set.str[STRING_UNIX_SOCKET_PATH]; ++ ++ hostaddr = calloc(1, sizeof(struct Curl_dns_entry)); ++ if(!hostaddr) ++ result = CURLE_OUT_OF_MEMORY; ++ else if((hostaddr->addr = Curl_unix2addr(path)) != NULL) ++ hostaddr->inuse++; ++ else { ++ /* Long paths are not supported for now */ ++ if(strlen(path) >= sizeof(((struct sockaddr_un *)0)->sun_path)) { ++ failf(data, "UNIX socket path too long: '%s'", path); ++ result = CURLE_COULDNT_RESOLVE_HOST; ++ } ++ else ++ result = CURLE_OUT_OF_MEMORY; ++ free(hostaddr); ++ hostaddr = NULL; ++ } ++ } ++ else ++#endif + if(!conn->proxy.name || !*conn->proxy.name) { + /* If not connecting via a proxy, extract the port from the URL, if it is + * there, thus overriding any defaults that might have been set above. */ +@@ -5071,6 +5108,13 @@ static CURLcode create_conn(struct SessionHandle *data, + else if(!proxy) + proxy = detect_proxy(conn); + ++#ifdef USE_UNIX_SOCKETS ++ if(proxy && data->set.str[STRING_UNIX_SOCKET_PATH]) { ++ free(proxy); /* UNIX domain sockets cannot be proxied, so disable it */ ++ proxy = NULL; ++ } ++#endif ++ + if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) { + free(proxy); /* Don't bother with an empty proxy string or if the + protocol doesn't work with network */ +diff --git a/lib/urldata.h b/lib/urldata.h +index b3ee7e3..723e40d 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -1375,6 +1375,10 @@ enum dupstring { + STRING_TLSAUTH_PASSWORD, /* TLS auth */ + #endif + ++#ifdef USE_UNIX_SOCKETS ++ STRING_UNIX_SOCKET_PATH, /* path to UNIX socket, if used */ ++#endif ++ + /* -- end of zero-terminated strings -- */ + + STRING_LASTZEROTERMINATED, +diff --git a/lib/version.c b/lib/version.c +index d39fe0c..e798738 100644 +--- a/lib/version.c ++++ b/lib/version.c +@@ -278,6 +278,9 @@ static curl_version_info_data version_info = { + #if defined(USE_TLS_SRP) + | CURL_VERSION_TLSAUTH_SRP + #endif ++#if defined(USE_UNIX_SOCKETS) ++ | CURL_VERSION_UNIX_SOCKETS ++#endif + , + NULL, /* ssl_version */ + 0, /* ssl_version_num, this is kept at zero */ +diff --git a/src/Makefile.in b/src/Makefile.in +index 5f739a9..948092f 100644 +--- a/src/Makefile.in ++++ b/src/Makefile.in +@@ -272,6 +272,7 @@ USE_OPENLDAP = @USE_OPENLDAP@ + USE_POLARSSL = @USE_POLARSSL@ + USE_SCHANNEL = @USE_SCHANNEL@ + USE_SSLEAY = @USE_SSLEAY@ ++USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@ + USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@ + VERSION = @VERSION@ + VERSIONED_FLAVOUR = @VERSIONED_FLAVOUR@ +diff --git a/src/tool_getparam.c b/src/tool_getparam.c +index 98d53a7..0cd84d5 100644 +--- a/src/tool_getparam.c ++++ b/src/tool_getparam.c +@@ -285,7 +285,8 @@ static const struct feat feats[] = { + {"krb4", CURL_VERSION_KERBEROS4}, + {"libz", CURL_VERSION_LIBZ}, + {"CharConv", CURL_VERSION_CONV}, +- {"TLS-SRP", CURL_VERSION_TLSAUTH_SRP} ++ {"TLS-SRP", CURL_VERSION_TLSAUTH_SRP}, ++ {"unix-sockets", CURL_VERSION_UNIX_SOCKETS} + }; + + ParameterError getparameter(char *flag, /* f or -long-flag */ +diff --git a/tests/server/Makefile.in b/tests/server/Makefile.in +index 0ca4380..055fe9b 100644 +--- a/tests/server/Makefile.in ++++ b/tests/server/Makefile.in +@@ -329,6 +329,7 @@ USE_OPENLDAP = @USE_OPENLDAP@ + USE_POLARSSL = @USE_POLARSSL@ + USE_SCHANNEL = @USE_SCHANNEL@ + USE_SSLEAY = @USE_SSLEAY@ ++USE_UNIX_SOCKETS = @USE_UNIX_SOCKETS@ + USE_WINDOWS_SSPI = @USE_WINDOWS_SSPI@ + VERSION = @VERSION@ + VERSIONED_FLAVOUR = @VERSIONED_FLAVOUR@ +-- +2.5.2 + + +From 877e40cd741b5b65f503236a6947e38c28a2d6ce Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Thu, 27 Nov 2014 23:59:26 +0100 +Subject: [PATCH 08/11] tool: add --unix-socket option + +Signed-off-by: Peter Wu + +Upstream-commit: c8644d1f638fdd8f4bf34fe64e910ba704fb26c0 +Signed-off-by: Kamil Dudka +--- + src/tool_cfgable.c | 1 + + src/tool_cfgable.h | 2 ++ + src/tool_getparam.c | 6 +++++- + src/tool_help.c | 1 + + src/tool_operate.c | 4 ++++ + 5 files changed, 13 insertions(+), 1 deletion(-) + +diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c +index da11f4a..2479b73 100644 +--- a/src/tool_cfgable.c ++++ b/src/tool_cfgable.c +@@ -98,6 +98,7 @@ void free_config_fields(struct Configurable *config) + + config->trace_stream = NULL; /* closed elsewhere when appropriate */ + ++ Curl_safefree(config->unix_socket_path); + Curl_safefree(config->writeout); + + config->errors = NULL; /* closed elsewhere when appropriate */ +diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h +index 1f6f948..a9b033b 100644 +--- a/src/tool_cfgable.h ++++ b/src/tool_cfgable.h +@@ -204,6 +204,8 @@ struct Configurable { + bool use_metalink; /* process given URLs as metalink XML file */ + metalinkfile *metalinkfile_list; /* point to the first node */ + metalinkfile *metalinkfile_last; /* point to the last/current node */ ++ ++ char *unix_socket_path; /* path to UNIX domain socket */ + }; /* struct Configurable */ + + void free_config_fields(struct Configurable *config); +diff --git a/src/tool_getparam.c b/src/tool_getparam.c +index 0cd84d5..57cf97d 100644 +--- a/src/tool_getparam.c ++++ b/src/tool_getparam.c +@@ -144,7 +144,7 @@ static const struct LongShort aliases[]= { + {"$v", "ssl-reqd", FALSE}, + /* 'ssl-reqd' new in 7.20.0, previously this was ftp-ssl-reqd */ + {"$w", "sessionid", FALSE}, +- /* �sessionid' listed as --no-sessionid in the help */ ++ /* ?sessionid' listed as --no-sessionid in the help */ + {"$x", "ftp-ssl-control", FALSE}, + {"$y", "ftp-ssl-ccc", FALSE}, + {"$j", "ftp-ssl-ccc-mode", TRUE}, +@@ -173,6 +173,7 @@ static const struct LongShort aliases[]= { + {"$H", "mail-auth", TRUE}, + {"$I", "post303", FALSE}, + {"$J", "metalink", FALSE}, ++ {"$M", "unix-socket", TRUE}, + {"0", "http1.0", FALSE}, + {"1", "tlsv1", FALSE}, + {"10", "tlsv1.0", FALSE}, +@@ -862,6 +863,9 @@ ParameterError getparameter(char *flag, /* f or -long-flag */ + #endif + break; + } ++ case 'M': /* --unix-socket */ ++ GetStr(&config->unix_socket_path, nextarg); ++ break; + } + break; + case '#': /* --progress-bar */ +diff --git a/src/tool_help.c b/src/tool_help.c +index f7cd618..3a64e35 100644 +--- a/src/tool_help.c ++++ b/src/tool_help.c +@@ -214,6 +214,7 @@ static const char *const helptext[] = { + " --tlsuser USER TLS username", + " --tlspassword STRING TLS password", + " --tlsauthtype STRING TLS authentication type (default SRP)", ++ " --unix-socket FILE Connect through this UNIX domain socket", + " -A, --user-agent STRING User-Agent to send to server (H)", + " -v, --verbose Make the operation more talkative", + " -V, --version Show version number and quit", +diff --git a/src/tool_operate.c b/src/tool_operate.c +index 4166fc2..7a13fcf 100644 +--- a/src/tool_operate.c ++++ b/src/tool_operate.c +@@ -1320,6 +1320,10 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) + if(config->mail_auth) + my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth); + ++ /* new in 7.40.0 */ ++ if(config->unix_socket_path) ++ my_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, config->unix_socket_path); ++ + /* initialize retry vars for loop below */ + retry_sleep_default = (config->retry_delay) ? + config->retry_delay*1000L : RETRY_SLEEP_DEFAULT; /* ms */ +-- +2.5.2 + + +From 60bdcf03a1696b3d09ad1c04824816766c513dcd Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Wed, 3 Dec 2014 02:35:12 +0100 +Subject: [PATCH 09/11] curl.1: added --unix-socket + +Upstream-commit: 7853c1cfe6fc7828afbb812791a383781aca3be3 +Signed-off-by: Kamil Dudka +--- + docs/curl.1 | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/docs/curl.1 b/docs/curl.1 +index 7f3571b..38fa084 100644 +--- a/docs/curl.1 ++++ b/docs/curl.1 +@@ -1471,6 +1471,9 @@ If this option is used several times, the last one will be used. + .IP "--trace-time" + Prepends a time stamp to each trace or verbose line that curl displays. + (Added in 7.14.0) ++.IP "--unix-socket " ++(HTTP) Connect through this UNIX domain socket, instead of using the ++network. (Added in 7.40.0) + .IP "-u, --user " + Specify the user name and password to use for server authentication. Overrides + \fI-n, --netrc\fP and \fI--netrc-optional\fP. +-- +2.5.2 + + +From af6fa1e00657c637d52cc24eab6d769b8eb793a9 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 4 Dec 2014 02:46:15 +0100 +Subject: [PATCH 10/11] updateconninfo: clear destination struct before + getsockname() + +Otherwise we may read uninitialized bytes later in the unix-domain +sockets case. + +Upstream-commit: 9730c9fb7075792a112b65a023379fad3ec8dda4 +Signed-off-by: Kamil Dudka +--- + lib/connect.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/connect.c b/lib/connect.c +index ba9ab92..5aa53fe 100644 +--- a/lib/connect.c ++++ b/lib/connect.c +@@ -630,6 +630,7 @@ void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) + } + + len = sizeof(struct Curl_sockaddr_storage); ++ memset(&ssloc, 0, sizeof(ssloc)); + if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) { + error = SOCKERRNO; + failf(data, "getsockname() failed with errno %d: %s", +-- +2.5.2 + + +From 8d951bb327fb6a1e107e044dbc179096883c4489 Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Thu, 4 Dec 2014 11:01:41 -0800 +Subject: [PATCH 11/11] tool: fix CURLOPT_UNIX_SOCKET_PATH in --libcurl output + +Mark CURLOPT_UNIX_SOCKET_PATH as string to ensure that it ends up as +option in the file generated by --libcurl. + +Signed-off-by: Peter Wu + +Upstream-commit: 2e557de09431854e4ad137cd741a582caa917517 +Signed-off-by: Kamil Dudka +--- + src/tool_operate.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/tool_operate.c b/src/tool_operate.c +index 7a13fcf..41b0e6b 100644 +--- a/src/tool_operate.c ++++ b/src/tool_operate.c +@@ -1322,7 +1322,8 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) + + /* new in 7.40.0 */ + if(config->unix_socket_path) +- my_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, config->unix_socket_path); ++ my_setopt_str(curl, CURLOPT_UNIX_SOCKET_PATH, ++ config->unix_socket_path); + + /* initialize retry vars for loop below */ + retry_sleep_default = (config->retry_delay) ? +-- +2.5.2 + diff --git a/SOURCES/0037-curl-7.29.0-fa7d04fe.patch b/SOURCES/0037-curl-7.29.0-fa7d04fe.patch new file mode 100644 index 0000000..e4517af --- /dev/null +++ b/SOURCES/0037-curl-7.29.0-fa7d04fe.patch @@ -0,0 +1,271 @@ +From 95924615ab42529e4dc7b95da1115346bf607fc6 Mon Sep 17 00:00:00 2001 +From: Jeremy Lin +Date: Mon, 15 Sep 2014 21:16:46 -0700 +Subject: [PATCH 1/2] ssh: improve key file search + +For private keys, use the first match from: user-specified key file +(if provided), ~/.ssh/id_rsa, ~/.ssh/id_dsa, ./id_rsa, ./id_dsa + +Note that the previous code only looked for id_dsa files. id_rsa is +now generally preferred, as it supports larger key sizes. + +For public keys, use the user-specified key file, if provided. +Otherwise, try to extract the public key from the private key file. +This means that passing --pubkey is typically no longer required, +and makes the key-handling behavior more like OpenSSH. + +Upstream-commit: fa7d04fed4d4578fe29bdff0b5465f6e4a7da81a +Signed-off-by: Kamil Dudka +--- + docs/MANUAL | 26 ++++++++++++++------- + docs/curl.1 | 8 ++++++- + lib/ssh.c | 75 +++++++++++++++++++++++++++++++++++++++---------------------- + 3 files changed, 73 insertions(+), 36 deletions(-) + +diff --git a/docs/MANUAL b/docs/MANUAL +index 4ad2e13..3f8d9b8 100644 +--- a/docs/MANUAL ++++ b/docs/MANUAL +@@ -41,12 +41,19 @@ SIMPLE USAGE + + Get a file from an SSH server using SFTP: + +- curl -u username sftp://shell.example.com/etc/issue ++ curl -u username sftp://example.com/etc/issue + +- Get a file from an SSH server using SCP using a private key to authenticate: ++ Get a file from an SSH server using SCP using a private key ++ (not password-protected) to authenticate: + +- curl -u username: --key ~/.ssh/id_dsa --pubkey ~/.ssh/id_dsa.pub \ +- scp://shell.example.com/~/personal.txt ++ curl -u username: --key ~/.ssh/id_rsa \ ++ scp://example.com/~/file.txt ++ ++ Get a file from an SSH server using SCP using a private key ++ (password-protected) to authenticate: ++ ++ curl -u username: --key ~/.ssh/id_rsa --pass private_key_password \ ++ scp://example.com/~/file.txt + + Get the main page from an IPv6 web server: + +@@ -91,10 +98,13 @@ USING PASSWORDS + + SFTP / SCP + +- This is similar to FTP, but you can specify a private key to use instead of +- a password. Note that the private key may itself be protected by a password +- that is unrelated to the login password of the remote system. If you +- provide a private key file you must also provide a public key file. ++ This is similar to FTP, but you can use the --key option to specify a ++ private key to use instead of a password. Note that the private key may ++ itself be protected by a password that is unrelated to the login password ++ of the remote system; this password is specified using the --pass option. ++ Typically, curl will automatically extract the public key from the private ++ key file, but in cases where curl does not have the proper library support, ++ a matching public key file must be specified using the --pubkey option. + + HTTP + +diff --git a/docs/curl.1 b/docs/curl.1 +index 38fa084..d1675a0 100644 +--- a/docs/curl.1 ++++ b/docs/curl.1 +@@ -724,7 +724,8 @@ If this option is used several times, the last one will be used. If + unspecified, the option defaults to 60 seconds. + .IP "--key " + (SSL/SSH) Private key file name. Allows you to provide your private key in this +-separate file. ++separate file. For SSH, if not specified, curl tries the following candidates ++in order: '~/.ssh/id_rsa', '~/.ssh/id_dsa', './id_rsa', './id_dsa'. + + If this option is used several times, the last one will be used. + .IP "--key-type " +@@ -1124,6 +1125,11 @@ protocol instead of the default HTTP 1.1. + separate file. + + If this option is used several times, the last one will be used. ++ ++(As of 7.39.0, curl attempts to automatically extract the public key from the ++private key file, so passing this option is generally not required. Note that ++this public key extraction requires libcurl to be linked against a copy of ++libssh2 1.2.8 or higher that is itself linked against OpenSSL.) + .IP "-q" + If used as the first parameter on the command line, the \fIcurlrc\fP config + file will not be read and used. See the \fI-K, --config\fP for details on the +diff --git a/lib/ssh.c b/lib/ssh.c +index 43e3342..4ea7d9b 100644 +--- a/lib/ssh.c ++++ b/lib/ssh.c +@@ -780,7 +780,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) + if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) && + (strstr(sshc->authlist, "publickey") != NULL)) { + char *home = NULL; +- bool rsa_pub_empty_but_ok = FALSE; ++ bool out_of_memory = FALSE; + + sshc->rsa_pub = sshc->rsa = NULL; + +@@ -788,34 +788,55 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) + HOME environment variable etc? */ + home = curl_getenv("HOME"); + +- if(data->set.str[STRING_SSH_PUBLIC_KEY] && +- !*data->set.str[STRING_SSH_PUBLIC_KEY]) +- rsa_pub_empty_but_ok = true; +- else if(data->set.str[STRING_SSH_PUBLIC_KEY]) +- sshc->rsa_pub = aprintf("%s", data->set.str[STRING_SSH_PUBLIC_KEY]); +- else if(home) +- sshc->rsa_pub = aprintf("%s/.ssh/id_dsa.pub", home); +- else +- /* as a final resort, try current dir! */ +- sshc->rsa_pub = strdup("id_dsa.pub"); +- +- if(!rsa_pub_empty_but_ok && (sshc->rsa_pub == NULL)) { +- Curl_safefree(home); +- state(conn, SSH_SESSION_FREE); +- sshc->actualcode = CURLE_OUT_OF_MEMORY; +- break; ++ if(data->set.str[STRING_SSH_PRIVATE_KEY]) ++ sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]); ++ else { ++ /* If no private key file is specified, try some common paths. */ ++ if(home) { ++ /* Try ~/.ssh first. */ ++ sshc->rsa = aprintf("%s/.ssh/id_rsa", home); ++ if(!sshc->rsa) ++ out_of_memory = TRUE; ++ else if(access(sshc->rsa, R_OK) != 0) { ++ Curl_safefree(sshc->rsa); ++ sshc->rsa = aprintf("%s/.ssh/id_dsa", home); ++ if(!sshc->rsa) ++ out_of_memory = TRUE; ++ else if(access(sshc->rsa, R_OK) != 0) { ++ Curl_safefree(sshc->rsa); ++ } ++ } ++ } ++ if(!out_of_memory && !sshc->rsa) { ++ /* Nothing found; try the current dir. */ ++ sshc->rsa = strdup("id_rsa"); ++ if(sshc->rsa && access(sshc->rsa, R_OK) != 0) { ++ Curl_safefree(sshc->rsa); ++ sshc->rsa = strdup("id_dsa"); ++ if(sshc->rsa && access(sshc->rsa, R_OK) != 0) { ++ Curl_safefree(sshc->rsa); ++ /* Out of guesses. Set to the empty string to avoid ++ * surprising info messages. */ ++ sshc->rsa = strdup(""); ++ } ++ } ++ } + } + +- if(data->set.str[STRING_SSH_PRIVATE_KEY]) +- sshc->rsa = aprintf("%s", data->set.str[STRING_SSH_PRIVATE_KEY]); +- else if(home) +- sshc->rsa = aprintf("%s/.ssh/id_dsa", home); +- else +- /* as a final resort, try current dir! */ +- sshc->rsa = strdup("id_dsa"); ++ /* ++ * Unless the user explicitly specifies a public key file, let ++ * libssh2 extract the public key from the private key file. ++ * This is done by simply passing sshc->rsa_pub = NULL. ++ */ ++ if(data->set.str[STRING_SSH_PUBLIC_KEY]) { ++ sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]); ++ if(!sshc->rsa_pub) ++ out_of_memory = TRUE; ++ } + +- if(sshc->rsa == NULL) { ++ if(out_of_memory || sshc->rsa == NULL) { + Curl_safefree(home); ++ Curl_safefree(sshc->rsa); + Curl_safefree(sshc->rsa_pub); + state(conn, SSH_SESSION_FREE); + sshc->actualcode = CURLE_OUT_OF_MEMORY; +@@ -828,8 +849,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) + + Curl_safefree(home); + +- infof(data, "Using ssh public key file %s\n", sshc->rsa_pub); +- infof(data, "Using ssh private key file %s\n", sshc->rsa); ++ infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub); ++ infof(data, "Using SSH private key file '%s'\n", sshc->rsa); + + state(conn, SSH_AUTH_PKEY); + } +-- +2.5.2 + + +From 2e18c6a12fc5dbab278670f22e58fcce51d32cac Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 15 Jan 2016 10:27:33 +0100 +Subject: [PATCH 2/2] ssh: make CURLOPT_SSH_PUBLIC_KEYFILE treat "" as NULL + +The CURLOPT_SSH_PUBLIC_KEYFILE option has been documented to handle +empty strings specially since curl-7_25_0-31-g05a443a but the behavior +was unintentionally removed in curl-7_38_0-47-gfa7d04f. + +This commit restores the original behavior and clarifies it in the +documentation that NULL and "" have both the same meaning when passed +to CURLOPT_SSH_PUBLIC_KEYFILE. + +Bug: http://curl.haxx.se/mail/lib-2016-01/0072.html + +Upstream-commit: be538e07667e1ba880b7201014be706851428d40 +Signed-off-by: Kamil Dudka +--- + docs/libcurl/curl_easy_setopt.3 | 6 +++--- + lib/ssh.c | 7 +++++-- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3 +index ad739e1..0a9375e 100644 +--- a/docs/libcurl/curl_easy_setopt.3 ++++ b/docs/libcurl/curl_easy_setopt.3 +@@ -2446,9 +2446,9 @@ Pass a char * pointing to a file name for your public key. If not used, + libcurl defaults to \fB$HOME/.ssh/id_dsa.pub\fP if the HOME environment + variable is set, and just "id_dsa.pub" in the current directory if HOME is not + set. (Added in 7.16.1) +-If an empty string is passed, libcurl will pass no public key to libssh2 +-which then tries to compute it from the private key, this is known to work +-when libssh2 1.4.0+ is linked against OpenSSL. (Added in 7.26.0) ++If NULL (or an empty string) is passed, libcurl will pass no public key to ++libssh2, which then tries to compute it from the private key. This is known ++to work with libssh2 1.4.0+ linked against OpenSSL. (Added in 7.26.0) + .IP CURLOPT_SSH_PRIVATE_KEYFILE + Pass a char * pointing to a file name for your private key. If not used, + libcurl defaults to \fB$HOME/.ssh/id_dsa\fP if the HOME environment variable +diff --git a/lib/ssh.c b/lib/ssh.c +index 4ea7d9b..589d4a3 100644 +--- a/lib/ssh.c ++++ b/lib/ssh.c +@@ -828,7 +828,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) + * libssh2 extract the public key from the private key file. + * This is done by simply passing sshc->rsa_pub = NULL. + */ +- if(data->set.str[STRING_SSH_PUBLIC_KEY]) { ++ if(data->set.str[STRING_SSH_PUBLIC_KEY] ++ /* treat empty string the same way as NULL */ ++ && data->set.str[STRING_SSH_PUBLIC_KEY][0]) { + sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]); + if(!sshc->rsa_pub) + out_of_memory = TRUE; +@@ -849,7 +851,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) + + Curl_safefree(home); + +- infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub); ++ if(sshc->rsa_pub) ++ infof(data, "Using SSH public key file '%s'\n", sshc->rsa_pub); + infof(data, "Using SSH private key file '%s'\n", sshc->rsa); + + state(conn, SSH_AUTH_PKEY); +-- +2.5.0 + diff --git a/SOURCES/0038-curl-7.29.0-958d2ffb.patch b/SOURCES/0038-curl-7.29.0-958d2ffb.patch new file mode 100644 index 0000000..d5e24f2 --- /dev/null +++ b/SOURCES/0038-curl-7.29.0-958d2ffb.patch @@ -0,0 +1,71 @@ +From f3fb07d2576c71a6409c0c1662c3b5ac61c283ab Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 18 Sep 2015 17:07:22 +0200 +Subject: [PATCH 1/2] nss: check return values of NSS functions + +Upstream-commit: a9fd53887ba07cd8313a8b9706f2dc71d6b8ed1b +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 0691394..763390d 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1491,9 +1491,13 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) + } + + /* Force handshake on next I/O */ +- SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE); ++ if(SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE) ++ != SECSuccess) ++ goto error; + +- SSL_SetURL(connssl->handle, conn->host.name); ++ /* propagate hostname to the TLS layer */ ++ if(SSL_SetURL(connssl->handle, conn->host.name) != SECSuccess) ++ goto error; + + return CURLE_OK; + +-- +2.5.2 + + +From 6b301701920a7b36df02bd94cdde259882e521d2 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 18 Sep 2015 17:10:05 +0200 +Subject: [PATCH 2/2] nss: prevent NSS from incorrectly re-using a session + +Without this workaround, NSS re-uses a session cache entry despite the +server name does not match. This causes SNI host name to differ from +the actual host name. Consequently, certain servers (e.g. github.com) +respond by 400 to such requests. + +Bug: https://bugzilla.mozilla.org/1202264 + +Upstream-commit: 958d2ffb198166a062a0ff20d009c64972a2b374 +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/lib/nss.c b/lib/nss.c +index 763390d..88d1a0d 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1499,6 +1499,10 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) + if(SSL_SetURL(connssl->handle, conn->host.name) != SECSuccess) + goto error; + ++ /* prevent NSS from re-using the session for a different hostname */ ++ if(SSL_SetSockPeerID(connssl->handle, conn->host.name) != SECSuccess) ++ goto error; ++ + return CURLE_OK; + + error: +-- +2.5.2 + diff --git a/SOURCES/0039-curl-7.29.0-4ef6b2d6.patch b/SOURCES/0039-curl-7.29.0-4ef6b2d6.patch new file mode 100644 index 0000000..8c623fc --- /dev/null +++ b/SOURCES/0039-curl-7.29.0-4ef6b2d6.patch @@ -0,0 +1,44 @@ +From 853653f4958e73bfd90a74a3ca910484ff86d9b0 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 12 Feb 2016 18:39:57 +0100 +Subject: [PATCH] curl.1: --disable-{eprt,epsv} are ignored for IPv6 hosts + +The behavior has been clarified in CURLOPT_FTP_USE_{EPRT,EPSV}.3 man +pages since curl-7_12_3~131. This patch makes it clear in the curl.1 +man page, too. + +Bug: https://bugzilla.redhat.com/1305970 + +Upstream-commit: 4ef6b2d6c60824d7c598a4ca8a70f0ef4fa3d443 +Signed-off-by: Kamil Dudka +--- + docs/curl.1 | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/docs/curl.1 b/docs/curl.1 +index d1675a0..ad26007 100644 +--- a/docs/curl.1 ++++ b/docs/curl.1 +@@ -357,6 +357,9 @@ the traditional PORT command. + \fB--eprt\fP can be used to explicitly enable EPRT again and \fB--no-eprt\fP + is an alias for \fB--disable-eprt\fP. + ++If the server is an IPv6 host, this option will have no effect as EPRT is ++necessary then. ++ + Disabling EPRT only changes the active behavior. If you want to switch to + passive mode you need to not use \fI-P, --ftp-port\fP or force it with + \fI--ftp-pasv\fP. +@@ -368,6 +371,9 @@ but with this option, it will not try using EPSV. + \fB--epsv\fP can be used to explicitly enable EPSV again and \fB--no-epsv\fP + is an alias for \fB--disable-epsv\fP. + ++If the server is an IPv6 host, this option will have no effect as EPSV is ++necessary then. ++ + Disabling EPSV only changes the passive behavior. If you want to switch to + active mode you need to use \fI-P, --ftp-port\fP. + .IP "-e, --referer " +-- +2.5.0 + diff --git a/SOURCES/0040-curl-7.29.0-513e587c.patch b/SOURCES/0040-curl-7.29.0-513e587c.patch new file mode 100644 index 0000000..b2720da --- /dev/null +++ b/SOURCES/0040-curl-7.29.0-513e587c.patch @@ -0,0 +1,218 @@ +From 070718b3e00d0341d44dd5ad4b48fd4468d047c6 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 9 Mar 2013 22:26:07 +0100 +Subject: [PATCH 1/3] curl_multi_wait: avoid second loop if nothing to do + +... hopefully this will also make clang-analyzer stop warning on +potentional NULL dereferences (which were false positives anyway). + +Upstream-commit: 136a3a0ee25f28fec1dde216467389f9e6e4f65c +Signed-off-by: Kamil Dudka +--- + lib/multi.c | 55 ++++++++++++++++++++++++++++++++----------------------- + 1 file changed, 32 insertions(+), 23 deletions(-) + +diff --git a/lib/multi.c b/lib/multi.c +index 6dfce9b..1136849 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -804,7 +804,8 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int bitmap; + unsigned int i; +- unsigned int nfds = extra_nfds; ++ unsigned int nfds = 0; ++ unsigned int curlfds; + struct pollfd *ufds = NULL; + long timeout_internal; + +@@ -842,6 +843,9 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, + easy = easy->next; /* check next handle */ + } + ++ curlfds = nfds; /* number of internal file descriptors */ ++ nfds += extra_nfds; /* add the externally provided ones */ ++ + if(nfds) { + ufds = malloc(nfds * sizeof(struct pollfd)); + if(!ufds) +@@ -849,32 +853,37 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, + } + nfds = 0; + +- /* Add the curl handles to our pollfds first */ +- easy=multi->easy.next; +- while(easy != &multi->easy) { +- bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE); ++ /* only do the second loop if we found descriptors in the first stage run ++ above */ + +- for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) { +- curl_socket_t s = CURL_SOCKET_BAD; ++ if(curlfds) { ++ /* Add the curl handles to our pollfds first */ ++ easy=multi->easy.next; ++ while(easy != &multi->easy) { ++ bitmap = multi_getsock(easy, sockbunch, MAX_SOCKSPEREASYHANDLE); + +- if(bitmap & GETSOCK_READSOCK(i)) { +- ufds[nfds].fd = sockbunch[i]; +- ufds[nfds].events = POLLIN; +- ++nfds; +- s = sockbunch[i]; +- } +- if(bitmap & GETSOCK_WRITESOCK(i)) { +- ufds[nfds].fd = sockbunch[i]; +- ufds[nfds].events = POLLOUT; +- ++nfds; +- s = sockbunch[i]; +- } +- if(s == CURL_SOCKET_BAD) { +- break; ++ for(i=0; i< MAX_SOCKSPEREASYHANDLE; i++) { ++ curl_socket_t s = CURL_SOCKET_BAD; ++ ++ if(bitmap & GETSOCK_READSOCK(i)) { ++ ufds[nfds].fd = sockbunch[i]; ++ ufds[nfds].events = POLLIN; ++ ++nfds; ++ s = sockbunch[i]; ++ } ++ if(bitmap & GETSOCK_WRITESOCK(i)) { ++ ufds[nfds].fd = sockbunch[i]; ++ ufds[nfds].events = POLLOUT; ++ ++nfds; ++ s = sockbunch[i]; ++ } ++ if(s == CURL_SOCKET_BAD) { ++ break; ++ } + } +- } + +- easy = easy->next; /* check next handle */ ++ easy = easy->next; /* check next handle */ ++ } + } + + /* Add external file descriptions from poll-like struct curl_waitfd */ +-- +2.5.5 + + +From f8b84a52088a99d8128c2234f626ed233beabeae Mon Sep 17 00:00:00 2001 +From: Evgeny Turnaev +Date: Thu, 18 Jul 2013 00:06:09 +0200 +Subject: [PATCH 2/3] curl_multi_wait: set revents for extra fds + +Pass back the revents that happened for the user-provided file +descriptors. + +Upstream-commit: 6d30f8ebed34e7276c2a59ee20d466bff17fee56 +Signed-off-by: Kamil Dudka +--- + lib/multi.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/lib/multi.c b/lib/multi.c +index 1136849..81bcfba 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -803,7 +803,7 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, + struct Curl_one_easy *easy; + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int bitmap; +- unsigned int i; ++ unsigned int i, j; + unsigned int nfds = 0; + unsigned int curlfds; + struct pollfd *ufds = NULL; +@@ -905,6 +905,9 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, + else + i = 0; + ++ for(j = nfds - extra_nfds; j < nfds; j++) ++ extra_fds[j].revents = ufds[j].revents; ++ + Curl_safefree(ufds); + if(ret) + *ret = i; +-- +2.5.5 + + +From db2e5b5ffe5408aa892dee9e7f036fe0ea16963d Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Thu, 18 Jul 2013 23:36:59 +0200 +Subject: [PATCH 3/3] curl_multi_wait: fix revents + +Commit 6d30f8ebed34e7276 didn't work properly. First, it used the wrong +array index, but this fix also: + +1 - only does the copying if indeed there was any activity + +2 - makes sure to properly translate between internal and external +bitfields, which are not guaranteed to match + +Reported-by: Evgeny Turnaev + +Upstream-commit: 513e587c5eb966038731530c8f47fe0cf27513ce +Signed-off-by: Kamil Dudka +--- + lib/multi.c | 28 +++++++++++++++++++++++----- + 1 file changed, 23 insertions(+), 5 deletions(-) + +diff --git a/lib/multi.c b/lib/multi.c +index 81bcfba..0e0bb19 100644 +--- a/lib/multi.c ++++ b/lib/multi.c +@@ -803,7 +803,7 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, + struct Curl_one_easy *easy; + curl_socket_t sockbunch[MAX_SOCKSPEREASYHANDLE]; + int bitmap; +- unsigned int i, j; ++ unsigned int i; + unsigned int nfds = 0; + unsigned int curlfds; + struct pollfd *ufds = NULL; +@@ -899,15 +899,33 @@ CURLMcode curl_multi_wait(CURLM *multi_handle, + ++nfds; + } + +- if(nfds) ++ if(nfds) { + /* wait... */ + i = Curl_poll(ufds, nfds, timeout_ms); ++ ++ if(i) { ++ unsigned int j; ++ /* copy revents results from the poll to the curl_multi_wait poll ++ struct, the bit values of the actual underlying poll() implementation ++ may not be the same as the ones in the public libcurl API! */ ++ for(j = 0; j < extra_nfds; j++) { ++ unsigned short mask = 0; ++ unsigned r = ufds[curlfds + j].revents; ++ ++ if(r & POLLIN) ++ mask |= CURL_WAIT_POLLIN; ++ if(r & POLLOUT) ++ mask |= CURL_WAIT_POLLOUT; ++ if(r & POLLPRI) ++ mask |= CURL_WAIT_POLLPRI; ++ ++ extra_fds[j].revents = mask; ++ } ++ } ++ } + else + i = 0; + +- for(j = nfds - extra_nfds; j < nfds; j++) +- extra_fds[j].revents = ufds[j].revents; +- + Curl_safefree(ufds); + if(ret) + *ret = i; +-- +2.5.5 + diff --git a/SOURCES/0041-curl-7.29.0-b2dcf034.patch b/SOURCES/0041-curl-7.29.0-b2dcf034.patch new file mode 100644 index 0000000..56a3567 --- /dev/null +++ b/SOURCES/0041-curl-7.29.0-b2dcf034.patch @@ -0,0 +1,59 @@ +From ac2121bf962ecc054dd103ccd42a93912051672e Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Tue, 21 Jun 2016 12:40:26 +0200 +Subject: [PATCH] curl-compilers.m4: improve detection of GCC's -fvisibility= + flag + +Some builds of GCC produce output on both stdout and stderr when --help +--verbose is used. The 2>&1 redirection caused them to be arbitrarily +interleaved with each other because of stream buffering. Consequently, +grep failed to match the fvisibility= string in the mixed output, even +though the string was present in GCC's standard output. + +This led to silently disabling symbol hiding in some builds of curl. + +Upstream-commit: b2dcf0347f1ee5041cccd64632bb8dd7ccbbae91 +Signed-off-by: Kamil Dudka +--- + configure | 2 +- + m4/curl-compilers.m4 | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/configure b/configure +index 4797e02..fc260ee 100755 +--- a/configure ++++ b/configure +@@ -17636,7 +17636,7 @@ $as_echo_n "checking if compiler supports hiding library internal symbols... " > + ;; + GNU_C) + if test "$compiler_num" -ge "304"; then +- if $CC --help --verbose 2>&1 | grep fvisibility= > /dev/null ; then ++ if $CC --help --verbose 2>/dev/null | grep fvisibility= >/dev/null ; then + tmp_EXTERN="__attribute__ ((__visibility__ (\"default\")))" + tmp_CFLAGS="-fvisibility=hidden" + supports_symbol_hiding="yes" +diff --git a/m4/curl-compilers.m4 b/m4/curl-compilers.m4 +index ca064dd..77371de 100644 +--- a/m4/curl-compilers.m4 ++++ b/m4/curl-compilers.m4 +@@ -21,7 +21,7 @@ + #*************************************************************************** + + # File version for 'aclocal' use. Keep it a single number. +-# serial 65 ++# serial 66 + + + dnl CURL_CHECK_COMPILER +@@ -1391,7 +1391,7 @@ AC_DEFUN([CURL_CHECK_COMPILER_SYMBOL_HIDING], [ + GNU_C) + dnl Only gcc 3.4 or later + if test "$compiler_num" -ge "304"; then +- if $CC --help --verbose 2>&1 | grep fvisibility= > /dev/null ; then ++ if $CC --help --verbose 2>/dev/null | grep fvisibility= >/dev/null ; then + tmp_EXTERN="__attribute__ ((__visibility__ (\"default\")))" + tmp_CFLAGS="-fvisibility=hidden" + supports_symbol_hiding="yes" +-- +2.5.5 + diff --git a/SOURCES/0042-curl-7.29.0-CVE-2016-5419.patch b/SOURCES/0042-curl-7.29.0-CVE-2016-5419.patch new file mode 100644 index 0000000..a634f25 --- /dev/null +++ b/SOURCES/0042-curl-7.29.0-CVE-2016-5419.patch @@ -0,0 +1,105 @@ +From a22c0daa87598a016bf0b5c93bb2ff63be5577f9 Mon Sep 17 00:00:00 2001 +From: Paul Donohue +Date: Tue, 15 Oct 2013 21:36:32 +0200 +Subject: [PATCH 1/2] NSS: acknowledge the + --no-sessionid/CURLOPT_SSL_SESSIONID_CACHE option + +Upstream-commit: f63603dec4519857498602f7a00acc0ffed29753 +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 83bb354..1f02988 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -1362,8 +1362,9 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex) + if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess) + goto error; + +- /* do not use SSL cache if we are not going to verify peer */ +- ssl_no_cache = (data->set.ssl.verifypeer) ? PR_FALSE : PR_TRUE; ++ /* do not use SSL cache if disabled or we are not going to verify peer */ ++ ssl_no_cache = (conn->ssl_config.sessionid && data->set.ssl.verifypeer) ? ++ PR_FALSE : PR_TRUE; + if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess) + goto error; + +-- +2.5.5 + + +From e164f1a355900f7f164d28ac9f937ad82d9ca45f Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Fri, 1 Jul 2016 13:32:31 +0200 +Subject: [PATCH 2/2] TLS: switch off SSL session id when client cert is used + +CVE-2016-5419 +Bug: https://curl.haxx.se/docs/adv_20160803A.html +Reported-by: Bru Rom +Contributions-by: Eric Rescorla and Ray Satiro + +Upstream-commit: 247d890da88f9ee817079e246c59f3d7d12fde5f +Signed-off-by: Kamil Dudka +--- + lib/sslgen.c | 10 ++++++++++ + lib/url.c | 1 + + lib/urldata.h | 1 + + 3 files changed, 12 insertions(+) + +diff --git a/lib/sslgen.c b/lib/sslgen.c +index 4875874..3036bb2 100644 +--- a/lib/sslgen.c ++++ b/lib/sslgen.c +@@ -147,6 +147,15 @@ Curl_clone_ssl_config(struct ssl_config_data *source, + else + dest->random_file = NULL; + ++ if(source->clientcert) { ++ dest->clientcert = strdup(source->clientcert); ++ if(!dest->clientcert) ++ return FALSE; ++ dest->sessionid = FALSE; ++ } ++ else ++ dest->clientcert = NULL; ++ + return TRUE; + } + +@@ -157,6 +166,7 @@ void Curl_free_ssl_config(struct ssl_config_data* sslc) + Curl_safefree(sslc->cipher_list); + Curl_safefree(sslc->egdsocket); + Curl_safefree(sslc->random_file); ++ Curl_safefree(sslc->clientcert); + } + + #ifdef USE_SSL +diff --git a/lib/url.c b/lib/url.c +index 7257b5e..959510d 100644 +--- a/lib/url.c ++++ b/lib/url.c +@@ -5255,6 +5255,7 @@ static CURLcode create_conn(struct SessionHandle *data, + data->set.ssl.random_file = data->set.str[STRING_SSL_RANDOM_FILE]; + data->set.ssl.egdsocket = data->set.str[STRING_SSL_EGDSOCKET]; + data->set.ssl.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST]; ++ data->set.ssl.clientcert = data->set.str[STRING_CERT]; + #ifdef USE_TLS_SRP + data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME]; + data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD]; +diff --git a/lib/urldata.h b/lib/urldata.h +index 723e40d..f4c6222 100644 +--- a/lib/urldata.h ++++ b/lib/urldata.h +@@ -340,6 +340,7 @@ struct ssl_config_data { + char *CAfile; /* certificate to verify peer against */ + const char *CRLfile; /* CRL to check certificate revocation */ + const char *issuercert;/* optional issuer certificate filename */ ++ char *clientcert; + char *random_file; /* path to file containing "random" data */ + char *egdsocket; /* path to file containing the EGD daemon socket */ + char *cipher_list; /* list of ciphers to use */ +-- +2.5.5 + diff --git a/SOURCES/0043-curl-7.29.0-CVE-2016-5420.patch b/SOURCES/0043-curl-7.29.0-CVE-2016-5420.patch new file mode 100644 index 0000000..532e974 --- /dev/null +++ b/SOURCES/0043-curl-7.29.0-CVE-2016-5420.patch @@ -0,0 +1,75 @@ +From 1b6dc2b543446401fd38795f1ccf2b93633f01c0 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sun, 31 Jul 2016 00:51:48 +0200 +Subject: [PATCH 1/2] TLS: only reuse connections with the same client cert + +CVE-2016-5420 +Bug: https://curl.haxx.se/docs/adv_20160803B.html + +Upstream-commit: 11ec5ad4352bba384404c56e77c7fab9382fd22d +Signed-off-by: Kamil Dudka +--- + lib/sslgen.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/sslgen.c b/lib/sslgen.c +index 3036bb2..79cbb6f 100644 +--- a/lib/sslgen.c ++++ b/lib/sslgen.c +@@ -90,6 +90,7 @@ Curl_ssl_config_matches(struct ssl_config_data* data, + (data->verifyhost == needle->verifyhost) && + safe_strequal(data->CApath, needle->CApath) && + safe_strequal(data->CAfile, needle->CAfile) && ++ safe_strequal(data->clientcert, needle->clientcert) && + safe_strequal(data->random_file, needle->random_file) && + safe_strequal(data->egdsocket, needle->egdsocket) && + safe_strequal(data->cipher_list, needle->cipher_list)) +-- +2.5.5 + + +From 1a7116f8607868b26355c512e5844a9b85f16daf Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 22 Aug 2016 10:24:35 +0200 +Subject: [PATCH 2/2] nss: refuse previously loaded certificate from file + +... when we are not asked to use a certificate from file + +Upstream-commit: 7700fcba64bf5806de28f6c1c7da3b4f0b38567d +Signed-off-by: Kamil Dudka +--- + lib/nss.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/lib/nss.c b/lib/nss.c +index 1f02988..7b4fe57 100644 +--- a/lib/nss.c ++++ b/lib/nss.c +@@ -760,10 +760,10 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, + struct ssl_connect_data *connssl = (struct ssl_connect_data *)arg; + struct SessionHandle *data = connssl->data; + const char *nickname = connssl->client_nickname; ++ static const char pem_slotname[] = "PEM Token #1"; + + if(connssl->obj_clicert) { + /* use the cert/key provided by PEM reader */ +- static const char pem_slotname[] = "PEM Token #1"; + SECItem cert_der = { 0, NULL, 0 }; + void *proto_win = SSL_RevealPinArg(sock); + struct CERTCertificateStr *cert; +@@ -825,6 +825,12 @@ static SECStatus SelectClientCert(void *arg, PRFileDesc *sock, + if(NULL == nickname) + nickname = "[unknown]"; + ++ if(!strncmp(nickname, pem_slotname, sizeof(pem_slotname) - 1U)) { ++ failf(data, "NSS: refusing previously loaded certificate from file: %s", ++ nickname); ++ return SECFailure; ++ } ++ + if(NULL == *pRetKey) { + failf(data, "NSS: private key not found for certificate: %s", nickname); + return SECFailure; +-- +2.7.4 + 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/0055-curl-7.29.0-CVE-2017-1000257.patch b/SOURCES/0055-curl-7.29.0-CVE-2017-1000257.patch new file mode 100644 index 0000000..b186946 --- /dev/null +++ b/SOURCES/0055-curl-7.29.0-CVE-2017-1000257.patch @@ -0,0 +1,36 @@ +From f8b7620e0578ef44e8fd958d32f348b535d1ab77 Mon Sep 17 00:00:00 2001 +From: Daniel Stenberg +Date: Sat, 7 Oct 2017 00:11:31 +0200 +Subject: [PATCH] imap: if a FETCH response has no size, don't call write + callback + +CVE-2017-1000257 + +Reported-by: Brian Carpenter and 0xd34db347 +Also detected by OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3586 + +Upstream-commit: 13c9a9ded3ae744a1e11cbc14e9146d9fa427040 +Signed-off-by: Kamil Dudka +--- + lib/imap.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/lib/imap.c b/lib/imap.c +index 48af290..4deba88 100644 +--- a/lib/imap.c ++++ b/lib/imap.c +@@ -1137,6 +1137,11 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn, int imapcode, + /* the conversion from curl_off_t to size_t is always fine here */ + chunk = (size_t)filesize; + ++ if(!chunk) { ++ /* no size, we're done with the data */ ++ state(conn, IMAP_STOP); ++ return CURLE_OK; ++ } + result = Curl_client_write(conn, CLIENTWRITE_BODY, pp->cache, chunk); + if(result) + return result; +-- +2.13.6 + diff --git a/SOURCES/0101-curl-7.29.0-multilib.patch b/SOURCES/0101-curl-7.29.0-multilib.patch new file mode 100644 index 0000000..38aa86c --- /dev/null +++ b/SOURCES/0101-curl-7.29.0-multilib.patch @@ -0,0 +1,72 @@ + curl-config.in | 16 +++------------- + docs/curl-config.1 | 4 +++- + libcurl.pc.in | 1 + + 3 files changed, 7 insertions(+), 14 deletions(-) + +diff --git a/curl-config.in b/curl-config.in +index 150004d..95d0759 100644 +--- a/curl-config.in ++++ b/curl-config.in +@@ -75,7 +75,7 @@ while test $# -gt 0; do + ;; + + --cc) +- echo "@CC@" ++ echo "gcc" + ;; + + --prefix) +@@ -142,24 +142,14 @@ while test $# -gt 0; do + ;; + + --libs) +- if test "X@libdir@" != "X/usr/lib" -a "X@libdir@" != "X/usr/lib64"; then +- CURLLIBDIR="-L@libdir@ " +- else +- CURLLIBDIR="" +- fi +- if test "X@REQUIRE_LIB_DEPS@" = "Xyes"; then +- echo ${CURLLIBDIR}-lcurl @LIBCURL_LIBS@ +- else +- echo ${CURLLIBDIR}-lcurl +- fi ++ pkg-config libcurl --libs + ;; + + --static-libs) +- echo @libdir@/libcurl.@libext@ @LDFLAGS@ @LIBCURL_LIBS@ + ;; + + --configure) +- echo @CONFIGURE_OPTIONS@ ++ pkg-config libcurl --variable=configure_options | sed 's/^"//;s/"$//' + ;; + + *) +diff --git a/docs/curl-config.1 b/docs/curl-config.1 +index c4f4e2b..3e0ea60 100644 +--- a/docs/curl-config.1 ++++ b/docs/curl-config.1 +@@ -65,7 +65,9 @@ be listed using uppercase and are separa + one, or several protocols in the list. (Added in 7.13.0) + .IP "--static-libs" + Shows the complete set of libs and other linker options you will need in order +-to link your application with libcurl statically. (Added in 7.17.1) ++to link your application with libcurl statically. Note that Fedora/RHEL libcurl ++packages do not provide any static libraries, thus cannot be linked statically. ++(Added in 7.17.1) + .IP "--version" + Outputs version information about the installed libcurl. + .IP "--vernum" +diff --git a/libcurl.pc.in b/libcurl.pc.in +index 2ba9c39..f8f8b00 100644 +--- a/libcurl.pc.in ++++ b/libcurl.pc.in +@@ -29,6 +29,7 @@ libdir=@libdir@ + includedir=@includedir@ + supported_protocols="@SUPPORT_PROTOCOLS@" + supported_features="@SUPPORT_FEATURES@" ++configure_options=@CONFIGURE_OPTIONS@ + + Name: libcurl + URL: http://curl.haxx.se/ diff --git a/SOURCES/0102-curl-7.29.0-debug.patch b/SOURCES/0102-curl-7.29.0-debug.patch new file mode 100644 index 0000000..090afdb --- /dev/null +++ b/SOURCES/0102-curl-7.29.0-debug.patch @@ -0,0 +1,65 @@ +From 6710648c2b270c9ce68a7d9f1bba1222c7be8b58 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 31 Oct 2012 11:38:30 +0100 +Subject: [PATCH] prevent configure script from discarding -g in CFLAGS (#496778) + +--- + configure | 13 +++---------- + m4/curl-compilers.m4 | 13 +++---------- + 2 files changed, 6 insertions(+), 20 deletions(-) + +diff --git a/configure b/configure +index 8f079a3..53b4774 100755 +--- a/configure ++++ b/configure +@@ -15819,18 +15819,11 @@ $as_echo "yes" >&6; } + gccvhi=`echo $gccver | cut -d . -f1` + gccvlo=`echo $gccver | cut -d . -f2` + compiler_num=`(expr $gccvhi "*" 100 + $gccvlo) 2>/dev/null` +- flags_dbg_all="-g -g0 -g1 -g2 -g3" +- flags_dbg_all="$flags_dbg_all -ggdb" +- flags_dbg_all="$flags_dbg_all -gstabs" +- flags_dbg_all="$flags_dbg_all -gstabs+" +- flags_dbg_all="$flags_dbg_all -gcoff" +- flags_dbg_all="$flags_dbg_all -gxcoff" +- flags_dbg_all="$flags_dbg_all -gdwarf-2" +- flags_dbg_all="$flags_dbg_all -gvms" ++ flags_dbg_all="" + flags_dbg_yes="-g" + flags_dbg_off="" +- flags_opt_all="-O -O0 -O1 -O2 -O3 -Os" +- flags_opt_yes="-O2" ++ flags_opt_all="" ++ flags_opt_yes="" + flags_opt_off="-O0" + + if test -z "$SED"; then +diff --git a/m4/curl-compilers.m4 b/m4/curl-compilers.m4 +index 0cbba7a..9175b5b 100644 +--- a/m4/curl-compilers.m4 ++++ b/m4/curl-compilers.m4 +@@ -148,18 +148,11 @@ AC_DEFUN([CURL_CHECK_COMPILER_GNU_C], [ + gccvhi=`echo $gccver | cut -d . -f1` + gccvlo=`echo $gccver | cut -d . -f2` + compiler_num=`(expr $gccvhi "*" 100 + $gccvlo) 2>/dev/null` +- flags_dbg_all="-g -g0 -g1 -g2 -g3" +- flags_dbg_all="$flags_dbg_all -ggdb" +- flags_dbg_all="$flags_dbg_all -gstabs" +- flags_dbg_all="$flags_dbg_all -gstabs+" +- flags_dbg_all="$flags_dbg_all -gcoff" +- flags_dbg_all="$flags_dbg_all -gxcoff" +- flags_dbg_all="$flags_dbg_all -gdwarf-2" +- flags_dbg_all="$flags_dbg_all -gvms" ++ flags_dbg_all="" + flags_dbg_yes="-g" + flags_dbg_off="" +- flags_opt_all="-O -O0 -O1 -O2 -O3 -Os" +- flags_opt_yes="-O2" ++ flags_opt_all="" ++ flags_opt_yes="" + flags_opt_off="-O0" + CURL_CHECK_DEF([_WIN32], [], [silent]) + else +-- +1.7.1 + 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/SOURCES/0104-curl-7.19.7-localhost6.patch b/SOURCES/0104-curl-7.19.7-localhost6.patch new file mode 100644 index 0000000..4f664d3 --- /dev/null +++ b/SOURCES/0104-curl-7.19.7-localhost6.patch @@ -0,0 +1,51 @@ +diff --git a/tests/data/test1083 b/tests/data/test1083 +index e441278..b0958b6 100644 +--- a/tests/data/test1083 ++++ b/tests/data/test1083 +@@ -33,13 +33,13 @@ ipv6 + http-ipv6 + + +-HTTP-IPv6 GET with ip6-localhost --interface ++HTTP-IPv6 GET with localhost6 --interface + + +--g "http://%HOST6IP:%HTTP6PORT/1083" --interface ip6-localhost ++-g "http://%HOST6IP:%HTTP6PORT/1083" --interface localhost6 + + +-perl -e "if ('%CLIENT6IP' ne '[::1]') {print 'Test requires default test server host address';} else {exec './server/resolve --ipv6 ip6-localhost'; print 'Cannot run precheck resolve';}" ++perl -e "if ('%CLIENT6IP' ne '[::1]') {print 'Test requires default test server host address';} else {exec './server/resolve --ipv6 localhost6'; print 'Cannot run precheck resolve';}" + + + +diff --git a/tests/data/test241 b/tests/data/test241 +index 46eae1f..4e1632c 100644 +--- a/tests/data/test241 ++++ b/tests/data/test241 +@@ -30,13 +30,13 @@ ipv6 + http-ipv6 + + +-HTTP-IPv6 GET (using ip6-localhost) ++HTTP-IPv6 GET (using localhost6) + + +--g "http://ip6-localhost:%HTTP6PORT/241" ++-g "http://localhost6:%HTTP6PORT/241" + + +-./server/resolve --ipv6 ip6-localhost ++./server/resolve --ipv6 localhost6 + + + +@@ -48,7 +48,7 @@ HTTP-IPv6 GET (using ip6-localhost) + + + GET /241 HTTP/1.1 +-Host: ip6-localhost:%HTTP6PORT ++Host: localhost6:%HTTP6PORT + Accept: */* + + diff --git a/SOURCES/0105-curl-7.32.0-scp-upload.patch b/SOURCES/0105-curl-7.32.0-scp-upload.patch new file mode 100644 index 0000000..c0fb0bf --- /dev/null +++ b/SOURCES/0105-curl-7.32.0-scp-upload.patch @@ -0,0 +1,42 @@ +From 2e973be50f75d0a85dcb995f7823f00b1fc85c2f Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Mon, 7 Oct 2013 16:07:50 +0200 +Subject: [PATCH] ssh: improve the logic for detecting blocking direction + +This fixes a regression introduced by commit 0feeab78 limiting the speed +of SCP upload to 16384 B/s on a fast connection (such as localhost). + +[upstream commit d015f4ccac627852869cb45e31ccdc9fbd97dc47] +--- + lib/ssh.c | 8 +++++--- + 1 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/lib/ssh.c b/lib/ssh.c +index 422357b..93c65c3 100644 +--- a/lib/ssh.c ++++ b/lib/ssh.c +@@ -2287,6 +2287,10 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block) + sshc->actualcode = result; + } + else { ++ /* store this original bitmask setup to use later on if we can't ++ figure out a "real" bitmask */ ++ sshc->orig_waitfor = data->req.keepon; ++ + /* we want to use the _sending_ function even when the socket turns + out readable as the underlying libssh2 scp send function will deal + with both accordingly */ +@@ -2603,9 +2607,7 @@ static void ssh_block2waitfor(struct connectdata *conn, bool block) + { + struct ssh_conn *sshc = &conn->proto.sshc; + int dir; +- if(!block) +- conn->waitfor = 0; +- else if((dir = libssh2_session_block_directions(sshc->ssh_session))) { ++ if(block && (dir = libssh2_session_block_directions(sshc->ssh_session))) { + /* translate the libssh2 define bits into our own bit defines */ + conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND)?KEEP_RECV:0) | + ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND)?KEEP_SEND:0); +-- +1.7.1 + diff --git a/SOURCES/0106-curl-7.21.0-libssh2-valgrind.patch b/SOURCES/0106-curl-7.21.0-libssh2-valgrind.patch new file mode 100644 index 0000000..2b8cb38 --- /dev/null +++ b/SOURCES/0106-curl-7.21.0-libssh2-valgrind.patch @@ -0,0 +1,31 @@ + tests/data/test604 | 3 +++ + tests/data/test623 | 4 +++- + 2 files changed, 6 insertions(+), 1 deletions(-) + +diff --git a/tests/data/test604 b/tests/data/test604 +index af0259f..2bcf7d1 100644 +--- a/tests/data/test604 ++++ b/tests/data/test604 +@@ -26,5 +26,8 @@ SFTP retrieval of nonexistent file + + 78 + ++ ++disable ++ + + +diff --git a/tests/data/test623 b/tests/data/test623 +index 19e505b..38a41d2 100644 +--- a/tests/data/test623 ++++ b/tests/data/test623 +@@ -36,6 +36,8 @@ for ssh upload test + + 79 + +- ++ ++disable ++ + + diff --git a/SOURCES/0107-curl-7.21.4-libidn-valgrind.patch b/SOURCES/0107-curl-7.21.4-libidn-valgrind.patch new file mode 100644 index 0000000..719b3a6 --- /dev/null +++ b/SOURCES/0107-curl-7.21.4-libidn-valgrind.patch @@ -0,0 +1,26 @@ +From d6c42a5bf66d4d458b20836573d6989e53f7d423 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Fri, 18 Feb 2011 17:49:59 +0100 +Subject: [PATCH] curl: work around valgrind bug (RHBZ#678518) + +https://bugs.kde.org/show_bug.cgi?id=264936 +--- + tests/data/test165 | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/tests/data/test165 b/tests/data/test165 +index ddfe1e9..b2cbc4f 100644 +--- a/tests/data/test165 ++++ b/tests/data/test165 +@@ -54,5 +54,8 @@ Accept: */* + Proxy-Connection: Keep-Alive + + ++ ++disable ++ + + +-- +1.7.4 + diff --git a/SOURCES/0108-curl-7.29.0-utf8.patch b/SOURCES/0108-curl-7.29.0-utf8.patch new file mode 100644 index 0000000..4829d1f --- /dev/null +++ b/SOURCES/0108-curl-7.29.0-utf8.patch @@ -0,0 +1,39 @@ +From c6246783cf347652f70d95c0562dd411747e9d53 Mon Sep 17 00:00:00 2001 +From: Kamil Dudka +Date: Wed, 31 Oct 2012 11:40:30 +0100 +Subject: [PATCH] Fix character encoding of docs + +..., which are of mixed encoding originally so a simple iconv can't +fix them. +--- + CHANGES | 2 +- + README | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/CHANGES b/CHANGES +index 4568408..5fc1652 100644 +--- a/CHANGES ++++ b/CHANGES +@@ -1910,7 +1910,7 @@ Daniel Stenberg (12 Nov 2012) + + - [Gabriel Sjoberg brought this change] + +- Digst: Add microseconds into nounce calculation ++ Digest: Add microseconds into nounce calculation + + When using only 1 second precision, curl doesn't create new cnonce + values quickly enough for all uses. +diff --git a/README b/README +index 2ffacc3..cfd6760 100644 +--- a/README ++++ b/README +@@ -45,5 +45,5 @@ GIT + NOTICE + + Curl contains pieces of source code that is Copyright (c) 1998, 1999 +- Kungliga Tekniska H�gskolan. This notice is included here to comply with the ++ Kungliga Tekniska Högskolan. This notice is included here to comply with the + distribution terms. +-- +1.7.1 + 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/SOURCES/curlbuild.h b/SOURCES/curlbuild.h new file mode 100644 index 0000000..b488626 --- /dev/null +++ b/SOURCES/curlbuild.h @@ -0,0 +1,9 @@ +#include + +#if __WORDSIZE == 32 +#include "curlbuild-32.h" +#elif __WORDSIZE == 64 +#include "curlbuild-64.h" +#else +#error "Unknown word size" +#endif diff --git a/SPECS/curl.spec b/SPECS/curl.spec new file mode 100644 index 0000000..1cd4453 --- /dev/null +++ b/SPECS/curl.spec @@ -0,0 +1,1494 @@ +Summary: A utility for getting files from remote servers (FTP, HTTP, and others) +Name: curl +Version: 7.29.0 +Release: 42%{?dist}.1 +License: MIT +Group: Applications/Internet +Source: http://curl.haxx.se/download/%{name}-%{version}.tar.lzma +Source2: curlbuild.h + +# fix a SIGSEGV when closing an unused multi handle (#914411) +Patch1: 0001-curl-7.29.0-da3fc1ee.patch + +# switch SSL socket into non-blocking mode after handshake +Patch2: 0002-curl-7.29.0-9d0af301.patch + +# do not ignore poll() failures other than EINTR +Patch3: 0003-curl-7.29.0-491e026c.patch + +# curl_global_init() now accepts the CURL_GLOBAL_ACK_EINTR flag +Patch4: 0004-curl-7.29.0-57ccdfa8.patch + +# fix cookie tailmatching to prevent cross-domain leakage (CVE-2013-1944) +Patch5: 0005-curl-7.29.0-2eb8dcf2.patch + +# show proper host name on failed resolve (#957173) +Patch6: 0006-curl-7.29.0-25e577b3.patch + +# prevent an artificial timeout event due to stale speed-check data (#906031) +Patch7: 0007-curl-7.29.0-b37b5233.patch + +# fix heap-based buffer overflow in curl_easy_unescape() (CVE-2013-2174) +Patch8: 0008-curl-7.29.0-192c4f78.patch + +# mention all option listed in 'curl --help' in curl.1 man page +Patch9: 0009-curl-7.29.0-3a0e931f.patch + +# FTP: when EPSV gets a 229 but fails to connect, retry with PASV (#1002815) +Patch10: 0010-curl-7.29.0-7cc00d9a.patch + +# avoid a busy-loop in curl_easy_perform() +Patch11: 0011-curl-7.29.0-0feeab78.patch + +# avoid delay if FTP is aborted in CURLOPT_HEADERFUNCTION callback (#1005686) +Patch12: 0012-curl-7.29.0-c639d725.patch + +# allow to use ECC ciphers if NSS implements them (#1058776) +Patch13: 0013-curl-7.29.0-665c160f.patch + +# re-use of wrong HTTP NTLM connection in libcurl (CVE-2014-0015) +Patch14: 0014-curl-7.29.0-8ae35102.patch + +# allow to use TLS > 1.0 if built against recent NSS (#1036789) +Patch15: 0015-curl-7.29.0-7fc9325a.patch + +# use proxy name in error message when proxy is used (#1042831) +Patch16: 0016-curl-7.29.0-1cf71bd7.patch + +# refresh expired cookie in test172 from upstream test-suite (#1063693) +Patch17: 0017-curl-7.29.0-ffb8a21d.patch + +# fix documentation of curl's options --tlsv1.[0-2] (#1066364) +Patch18: 0018-curl-7.29.0-03c28820.patch + +# fix connection re-use when using different log-in credentials (CVE-2014-0138) +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 + +# prevent test46 from failing due to expired cookie (#1258834) +Patch34: 0034-curl-7.29.0-002d58f1.patch + +# improve parsing of URL-encoded user name and password (#1260178) +Patch35: 0035-curl-7.29.0-2f1a0bc0.patch + +# implement 'curl --unix-socket' and CURLOPT_UNIX_SOCKET_PATH (#1263318) +Patch36: 0036-curl-7.29.0-c8644d1f.patch + +# SSH: do not require public key file for user authentication (#1275769) +Patch37: 0037-curl-7.29.0-fa7d04fe.patch + +# prevent NSS from incorrectly re-using a session (#1269855) +Patch38: 0038-curl-7.29.0-958d2ffb.patch + +# curl.1: --disable-{eprt,epsv} are ignored for IPv6 hosts (#1305974) +Patch39: 0039-curl-7.29.0-4ef6b2d6.patch + +# prevent curl_multi_wait() from missing an event (#1347904) +Patch40: 0040-curl-7.29.0-513e587c.patch + +# configure: improve detection of GCC's -fvisibility= flag +Patch41: 0041-curl-7.29.0-b2dcf034.patch + +# fix TLS session resumption client cert bypass (CVE-2016-5419) +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 + +# fix buffer overflow while processing IMAP FETCH response (CVE-2017-1000257) +Patch55: 0055-curl-7.29.0-CVE-2017-1000257.patch + +# patch making libcurl multilib ready +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 + +# disable valgrind for certain test-cases (libssh2 problem) +Patch106: 0106-curl-7.21.0-libssh2-valgrind.patch + +# http://thread.gmane.org/gmane.comp.web.curl.library/40551/focus=40561 +Patch105: 0105-curl-7.32.0-scp-upload.patch + +# work around valgrind bug (#678518) +Patch107: 0107-curl-7.21.4-libidn-valgrind.patch + +# Fix character encoding of docs, which are of mixed encoding originally so +# 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 +BuildRequires: libssh2-devel +BuildRequires: nss-devel +BuildRequires: openldap-devel +BuildRequires: openssh-clients +BuildRequires: openssh-server +BuildRequires: pkgconfig +BuildRequires: stunnel +BuildRequires: zlib-devel + +# perl modules used in the test suite +BuildRequires: perl(Cwd) +BuildRequires: perl(Digest::MD5) +BuildRequires: perl(Exporter) +BuildRequires: perl(File::Basename) +BuildRequires: perl(File::Copy) +BuildRequires: perl(File::Spec) +BuildRequires: perl(IPC::Open2) +BuildRequires: perl(MIME::Base64) +BuildRequires: perl(strict) +BuildRequires: perl(Time::Local) +BuildRequires: perl(Time::HiRes) +BuildRequires: perl(warnings) +BuildRequires: perl(vars) + +# require valgrind to boost test coverage on i386 and x86_64 +%ifarch %{ix86} x86_64 +BuildRequires: valgrind +%endif + +Requires: libcurl = %{version}-%{release} + +# require at least the version of libssh2 that we were built against, +# to ensure that we have the necessary symbols available (#525002, #642796) +%global libssh2_version %(pkg-config --modversion libssh2 2>/dev/null || echo 0) + +%description +curl is a command line tool for transferring data with URL syntax, supporting +FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS, FILE, IMAP, +SMTP, POP3 and RTSP. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP +uploading, HTTP form based upload, proxies, cookies, user+password +authentication (Basic, Digest, NTLM, Negotiate, kerberos...), file transfer +resume, proxy tunneling and a busload of other useful tricks. + +%package -n libcurl +Summary: A library for getting files from web servers +Group: Development/Libraries +Requires: libssh2%{?_isa} >= %{libssh2_version} + +%description -n libcurl +libcurl is a free and easy-to-use client-side URL transfer library, supporting +FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS, FILE, IMAP, +SMTP, POP3 and RTSP. libcurl supports SSL certificates, HTTP POST, HTTP PUT, +FTP uploading, HTTP form based upload, proxies, cookies, user+password +authentication (Basic, Digest, NTLM, Negotiate, Kerberos4), file transfer +resume, http proxy tunneling and more. + +%package -n libcurl-devel +Summary: Files needed for building applications with libcurl +Group: Development/Libraries +Requires: libcurl = %{version}-%{release} + +# From Fedora 14, %%{_datadir}/aclocal is included in the filesystem package +%if 0%{?fedora} < 14 +Requires: %{_datadir}/aclocal +%endif + +# From Fedora 11, RHEL-6, pkgconfig dependency is auto-detected +%if 0%{?fedora} < 11 && 0%{?rhel} < 6 +Requires: pkgconfig +%endif + +Provides: curl-devel = %{version}-%{release} +Obsoletes: curl-devel < %{version}-%{release} + +%description -n libcurl-devel +The libcurl-devel package includes header files and libraries necessary for +developing programs which use the libcurl library. It contains the API +documentation of the library, too. + +%prep +%setup -q + +# upstream patches +%patch1 -p1 +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch105 -p1 +%patch19 -p1 +%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 +%patch34 -p1 +%patch35 -p1 +%patch36 -p1 +%patch37 -p1 +%patch38 -p1 +%patch39 -p1 +%patch40 -p1 + +# Fedora/RHEL patches +%patch101 -p1 +%patch102 -p1 +%patch103 -p1 +%patch104 -p1 +%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 + +# 7.4.z +%patch55 -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 + +# disable test 1319 on ppc64 (server times out) +%ifarch ppc64 +echo "1319" >> tests/data/DISABLED +%endif + +%build +[ -x /usr/kerberos/bin/krb5-config ] && KRB5_PREFIX="=/usr/kerberos" +%configure --disable-static \ + --enable-hidden-symbols \ + --enable-ipv6 \ + --enable-ldaps \ + --enable-manual \ + --enable-threaded-resolver \ + --with-ca-bundle=%{_sysconfdir}/pki/tls/certs/ca-bundle.crt \ + --with-gssapi${KRB5_PREFIX} \ + --with-libidn \ + --with-libssh2 \ + --without-ssl --with-nss +# --enable-debug +# use ^^^ to turn off optimizations, etc. + +# Remove bogus rpath +sed -i \ + -e 's|^hardcode_libdir_flag_spec=.*|hardcode_libdir_flag_spec=""|g' \ + -e 's|^runpath_var=LD_RUN_PATH|runpath_var=DIE_RPATH_DIE|g' libtool + +make %{?_smp_mflags} + +%check +LD_LIBRARY_PATH=$RPM_BUILD_ROOT%{_libdir} +export LD_LIBRARY_PATH + +# uncomment to use the non-stripped library in tests +# LD_LIBRARY_PATH=$(dirname $(realpath $(find -name \*.so))) + +cd tests +make %{?_smp_mflags} + +# use different port range for 32bit and 64bit build, thus make it possible +# to run both in parallel on the same machine +./runtests.pl -a -b%{?__isa_bits}90 -p -v + +%install +rm -rf $RPM_BUILD_ROOT + +make DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p" install + +rm -f ${RPM_BUILD_ROOT}%{_libdir}/libcurl.la + +install -d $RPM_BUILD_ROOT%{_datadir}/aclocal +install -m 644 docs/libcurl/libcurl.m4 $RPM_BUILD_ROOT%{_datadir}/aclocal + +# drop man page for a script we do not distribute +rm -f ${RPM_BUILD_ROOT}%{_mandir}/man1/mk-ca-bundle.1 + +# Make libcurl-devel multilib-ready (bug #488922) +%if 0%{?__isa_bits} == 64 +%define _curlbuild_h curlbuild-64.h +%else +%define _curlbuild_h curlbuild-32.h +%endif +mv $RPM_BUILD_ROOT%{_includedir}/curl/curlbuild.h \ + $RPM_BUILD_ROOT%{_includedir}/curl/%{_curlbuild_h} + +install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_includedir}/curl/curlbuild.h + +%clean +rm -rf $RPM_BUILD_ROOT + +%post -n libcurl -p /sbin/ldconfig + +%postun -n libcurl -p /sbin/ldconfig + +%files +%defattr(-,root,root,-) +%doc CHANGES README* COPYING +%doc docs/BUGS docs/FAQ docs/FEATURES +%doc docs/MANUAL docs/RESOURCES +%doc docs/TheArtOfHttpScripting docs/TODO +%{_bindir}/curl +%{_mandir}/man1/curl.1* + +%files -n libcurl +%defattr(-,root,root,-) +%{_libdir}/libcurl.so.* + +%files -n libcurl-devel +%defattr(-,root,root,-) +%doc docs/examples/*.c docs/examples/Makefile.example docs/INTERNALS +%doc docs/CONTRIBUTE docs/libcurl/ABI +%{_bindir}/curl-config* +%{_includedir}/curl +%{_libdir}/*.so +%{_libdir}/pkgconfig/*.pc +%{_mandir}/man1/curl-config.1* +%{_mandir}/man3/* +%{_datadir}/aclocal/libcurl.m4 + +%changelog +* Mon Oct 23 2017 Kamil Dudka - 7.29.0-42.el7_4.1 +- fix buffer overflow while processing IMAP FETCH response (CVE-2017-1000257) + +* 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) + +* Wed Aug 17 2016 Kamil Dudka 7.29.0-34 +- acknowledge the --no-sessionid/CURLOPT_SSL_SESSIONID_CACHE option + (required by the fix for CVE-2016-5419) + +* Thu Aug 11 2016 Kamil Dudka 7.29.0-33 +- fix re-using connections with wrong client cert (CVE-2016-5420) +- fix TLS session resumption client cert bypass (CVE-2016-5419) + +* Mon Jun 20 2016 Kamil Dudka 7.29.0-32 +- configure: improve detection of GCC's -fvisibility= flag + +* Mon Jun 20 2016 Kamil Dudka 7.29.0-31 +- prevent curl_multi_wait() from missing an event (#1347904) + +* Tue Feb 16 2016 Kamil Dudka 7.29.0-30 +- curl.1: --disable-{eprt,epsv} are ignored for IPv6 hosts (#1305974) + +* Fri Jan 15 2016 Kamil Dudka 7.29.0-29 +- SSH: make CURLOPT_SSH_PUBLIC_KEYFILE treat "" as NULL (#1275769) + +* Mon Nov 02 2015 Kamil Dudka 7.29.0-28 +- prevent NSS from incorrectly re-using a session (#1269855) +- call PR_Cleanup() in the upstream test-suite if NSPR is used (#1243324) +- disable unreliable upstream test-case 2032 (#1241168) + +* Tue Oct 27 2015 Kamil Dudka 7.29.0-27 +- SSH: do not require public key file for user authentication (#1275769) + +* Tue Sep 08 2015 Kamil Dudka 7.29.0-26 +- implement 'curl --unix-socket' and CURLOPT_UNIX_SOCKET_PATH (#1263318) +- improve parsing of URL-encoded user name and password (#1260178) +- prevent test46 from failing due to expired cookie (#1258834) + +* 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) + +* Mon Mar 17 2014 Paul Howarth 7.29.0-18 +- add all perl build requirements for the test suite, in a portable way + +* Tue Feb 18 2014 Kamil Dudka 7.29.0-17 +- fix documentation of curl's options --tlsv1.[0-2] (#1066364) + +* Tue Feb 11 2014 Kamil Dudka 7.29.0-16 +- allow to use TLS > 1.0 if built against recent NSS (#1036789) +- use proxy name in error message when proxy is used (#1042831) +- refresh expired cookie in test172 from upstream test-suite (#1063693) + +* Fri Jan 31 2014 Kamil Dudka 7.29.0-15 +- allow to use ECC ciphers if NSS implements them (#1058776) +- re-use of wrong HTTP NTLM connection in libcurl (CVE-2014-0015) + +* Fri Jan 24 2014 Daniel Mach - 7.29.0-14 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 7.29.0-13 +- Mass rebuild 2013-12-27 + +* Fri Oct 11 2013 Kamil Dudka 7.29.0-12 +- do not limit the speed of SCP upload on a fast connection (#1014928) + +* Mon Sep 09 2013 Kamil Dudka 7.29.0-11 +- avoid delay if FTP is aborted in CURLOPT_HEADERFUNCTION callback (#1005686) + +* Wed Sep 04 2013 Kamil Dudka 7.29.0-10 +- avoid a busy-loop in curl_easy_perform() + +* Fri Aug 30 2013 Kamil Dudka 7.29.0-9 +- FTP: when EPSV gets a 229 but fails to connect, retry with PASV (#1002815) + +* Tue Jul 09 2013 Kamil Dudka 7.29.0-8 +- mention all option listed in 'curl --help' in curl.1 man page + +* Sat Jun 22 2013 Kamil Dudka 7.29.0-7 +- fix heap-based buffer overflow in curl_easy_unescape() (CVE-2013-2174) + +* Fri Apr 26 2013 Kamil Dudka 7.29.0-6 +- prevent an artificial timeout event due to stale speed-check data (#906031) +- show proper host name on failed resolve (#957173) + +* Fri Apr 12 2013 Kamil Dudka 7.29.0-5 +- fix cookie tailmatching to prevent cross-domain leakage (CVE-2013-1944) + +* Tue Mar 12 2013 Kamil Dudka 7.29.0-4 +- do not ignore poll() failures other than EINTR (#919127) +- curl_global_init() now accepts the CURL_GLOBAL_ACK_EINTR flag (#919127) + +* Wed Mar 06 2013 Kamil Dudka 7.29.0-3 +- switch SSL socket into non-blocking mode after handshake (#960765) +- drop the hide_selinux.c hack no longer needed in %%check + +* Fri Feb 22 2013 Kamil Dudka 7.29.0-2 +- fix a SIGSEGV when closing an unused multi handle (#914411) + +* Wed Feb 06 2013 Kamil Dudka 7.29.0-1 +- new upstream release (fixes CVE-2013-0249) + +* Tue Jan 15 2013 Kamil Dudka 7.28.1-3 +- require valgrind for build only on i386 and x86_64 (#886891) + +* Tue Jan 15 2013 Kamil Dudka 7.28.1-2 +- prevent NSS from crashing on client auth hook failure +- clear session cache if a client cert from file is used +- fix error messages for CURLE_SSL_{CACERT,CRL}_BADFILE + +* Tue Nov 20 2012 Kamil Dudka 7.28.1-1 +- new upstream release + +* Wed Oct 31 2012 Kamil Dudka 7.28.0-1 +- new upstream release + +* Mon Oct 01 2012 Kamil Dudka 7.27.0-3 +- use the upstream facility to disable problematic tests +- do not crash if MD5 fingerprint is not provided by libssh2 + +* Wed Aug 01 2012 Kamil Dudka 7.27.0-2 +- eliminate unnecessary inotify events on upload via file protocol (#844385) + +* Sat Jul 28 2012 Kamil Dudka 7.27.0-1 +- new upstream release + +* Mon Jul 23 2012 Kamil Dudka 7.26.0-6 +- print reason phrase from HTTP status line on error (#676596) + +* Wed Jul 18 2012 Fedora Release Engineering - 7.26.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Sat Jun 09 2012 Kamil Dudka 7.26.0-4 +- fix duplicated SSL handshake with multi interface and proxy (#788526) + +* Wed May 30 2012 Karsten Hopp 7.26.0-3 +- disable test 1319 on ppc64, server times out + +* Mon May 28 2012 Kamil Dudka 7.26.0-2 +- use human-readable error messages provided by NSS (upstream commit 72f4b534) + +* Fri May 25 2012 Kamil Dudka 7.26.0-1 +- new upstream release + +* Wed Apr 25 2012 Karsten Hopp 7.25.0-3 +- valgrind on ppc64 works fine, disable ppc32 only + +* Wed Apr 25 2012 Karsten Hopp 7.25.0-3 +- drop BR valgrind on PPC(64) until bugzilla #810992 gets fixed + +* Fri Apr 13 2012 Kamil Dudka 7.25.0-2 +- use NSS_InitContext() to initialize NSS if available (#738456) +- provide human-readable names for NSS errors (upstream commit a60edcc6) + +* Fri Mar 23 2012 Paul Howarth 7.25.0-1 +- new upstream release (#806264) +- fix character encoding of docs with a patch rather than just iconv +- update debug and multilib patches +- don't use macros for commands +- reduce size of %%prep output for readability + +* Tue Jan 24 2012 Kamil Dudka 7.24.0-1 +- new upstream release (fixes CVE-2012-0036) + +* Thu Jan 05 2012 Paul Howarth 7.23.0-6 +- rebuild for gcc 4.7 + +* Mon Jan 02 2012 Kamil Dudka 7.23.0-5 +- upstream patch that allows to run FTPS tests with nss-3.13 (#760060) + +* Tue Dec 27 2011 Kamil Dudka 7.23.0-4 +- allow to run FTPS tests with nss-3.13 (#760060) + +* Sun Dec 25 2011 Kamil Dudka 7.23.0-3 +- avoid unnecessary timeout event when waiting for 100-continue (#767490) + +* Mon Nov 21 2011 Kamil Dudka 7.23.0-2 +- curl -JO now uses -O name if no C-D header comes (upstream commit c532604) + +* Wed Nov 16 2011 Kamil Dudka 7.23.0-1 +- new upstream release (#754391) + +* Mon Sep 19 2011 Kamil Dudka 7.22.0-2 +- nss: select client certificates by DER (#733657) + +* Tue Sep 13 2011 Kamil Dudka 7.22.0-1 +- new upstream release +- curl-config now provides dummy --static-libs option (#733956) + +* Sun Aug 21 2011 Paul Howarth 7.21.7-4 +- actually fix SIGSEGV of curl -O -J given more than one URL (#723075) + +* Mon Aug 15 2011 Kamil Dudka 7.21.7-3 +- fix SIGSEGV of curl -O -J given more than one URL (#723075) +- introduce the --delegation option of curl (#730444) +- initialize NSS with no database if the selected database is broken (#728562) + +* Wed Aug 03 2011 Kamil Dudka 7.21.7-2 +- add a new option CURLOPT_GSSAPI_DELEGATION (#719939) + +* Thu Jun 23 2011 Kamil Dudka 7.21.7-1 +- new upstream release (fixes CVE-2011-2192) + +* Wed Jun 08 2011 Kamil Dudka 7.21.6-2 +- avoid an invalid timeout event on a reused handle (#679709) + +* Sat Apr 23 2011 Paul Howarth 7.21.6-1 +- new upstream release + +* Mon Apr 18 2011 Kamil Dudka 7.21.5-2 +- fix the output of curl-config --version (upstream commit 82ecc85) + +* Mon Apr 18 2011 Kamil Dudka 7.21.5-1 +- new upstream release + +* Sat Apr 16 2011 Peter Robinson 7.21.4-4 +- no valgrind on ARMv5 arches + +* Sat Mar 05 2011 Dennis Gilmore 7.21.4-3 +- no valgrind on sparc arches + +* Tue Feb 22 2011 Kamil Dudka 7.21.4-2 +- do not ignore failure of SSL handshake (upstream commit 7aa2d10) + +* Fri Feb 18 2011 Kamil Dudka 7.21.4-1 +- new upstream release +- avoid memory leak on SSL connection failure (upstream commit a40f58d) +- work around valgrind bug (#678518) + +* Tue Feb 08 2011 Fedora Release Engineering - 7.21.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Jan 12 2011 Kamil Dudka 7.21.3-2 +- build libcurl with --enable-hidden-symbols + +* Thu Dec 16 2010 Paul Howarth 7.21.3-1 +- update to 7.21.3: + - added --noconfigure switch to testcurl.pl + - added --xattr option + - added CURLOPT_RESOLVE and --resolve + - added CURLAUTH_ONLY + - added version-check.pl to the examples dir + - check for libcurl features for some command line options + - Curl_setopt: disallow CURLOPT_USE_SSL without SSL support + - http_chunks: remove debug output + - URL-parsing: consider ? a divider + - SSH: avoid using the libssh2_ prefix + - SSH: use libssh2_session_handshake() to work on win64 + - ftp: prevent server from hanging on closed data connection when stopping + a transfer before the end of the full transfer (ranges) + - LDAP: detect non-binary attributes properly + - ftp: treat server's response 421 as CURLE_OPERATION_TIMEDOUT + - gnutls->handshake: improved timeout handling + - security: pass the right parameter to init + - krb5: use GSS_ERROR to check for error + - TFTP: resend the correct data + - configure: fix autoconf 2.68 warning: no AC_LANG_SOURCE call detected + - GnuTLS: now detects socket errors on Windows + - symbols-in-versions: updated en masse + - added a couple of examples that were missing from the tarball + - Curl_send/recv_plain: return errno on failure + - Curl_wait_for_resolv (for c-ares): correct timeout + - ossl_connect_common: detect connection re-use + - configure: prevent link errors with --librtmp + - openldap: use remote port in URL passed to ldap_init_fd() + - url: provide dead_connection flag in Curl_handler::disconnect + - lots of compiler warning fixes + - ssh: fix a download resume point calculation + - fix getinfo CURLINFO_LOCAL* for reused connections + - multi: the returned running handles counter could turn negative + - multi: only ever consider pipelining for connections doing HTTP(S) +- drop upstream patches now in tarball +- update bz650255 and disable-test1112 patches to apply against new codebase +- add workaround for false-positive glibc-detected buffer overflow in tftpd + test server with FORTIFY_SOURCE (similar to #515361) + +* Fri Nov 12 2010 Kamil Dudka 7.21.2-5 +- do not send QUIT to a dead FTP control connection (#650255) +- pull back glibc's implementation of str[n]casecmp(), #626470 appears fixed + +* Tue Nov 09 2010 Kamil Dudka 7.21.2-4 +- prevent FTP client from hanging on unrecognized ABOR response (#649347) +- return more appropriate error code in case FTP server session idle + timeout has exceeded (#650255) + +* Fri Oct 29 2010 Kamil Dudka 7.21.2-3 +- prevent FTP server from hanging on closed data connection (#643656) + +* Thu Oct 14 2010 Paul Howarth 7.21.2-2 +- enforce versioned libssh2 dependency for libcurl (#642796) + +* Wed Oct 13 2010 Kamil Dudka 7.21.2-1 +- new upstream release, drop applied patches +- make 0102-curl-7.21.2-debug.patch less intrusive + +* Wed Sep 29 2010 jkeating - 7.21.1-6 +- Rebuilt for gcc bug 634757 + +* Sat Sep 11 2010 Kamil Dudka 7.21.1-5 +- make it possible to run SCP/SFTP tests on x86_64 (#632914) + +* Tue Sep 07 2010 Kamil Dudka 7.21.1-4 +- work around glibc/valgrind problem on x86_64 (#631449) + +* Tue Aug 24 2010 Paul Howarth 7.21.1-3 +- fix up patches so there's no need to run autotools in the rpm build +- drop buildreq automake +- drop dependency on automake for devel package from F-14, where + %%{_datadir}/aclocal is included in the filesystem package +- drop dependency on pkgconfig for devel package from F-11, where + pkgconfig dependencies are auto-generated + +* Mon Aug 23 2010 Kamil Dudka 7.21.1-2 +- re-enable test575 on s390(x), already fixed (upstream commit d63bdba) +- modify system headers to work around gcc bug (#617757) +- curl -T now ignores file size of special files (#622520) +- fix kerberos proxy authentication for https (#625676) +- work around glibc/valgrind problem on x86_64 (#626470) + +* Thu Aug 12 2010 Kamil Dudka 7.21.1-1 +- new upstream release + +* Mon Jul 12 2010 Dan Horák 7.21.0-3 +- disable test 575 on s390(x) + +* Mon Jun 28 2010 Kamil Dudka 7.21.0-2 +- add support for NTLM authentication (#603783) + +* Wed Jun 16 2010 Kamil Dudka 7.21.0-1 +- new upstream release, drop applied patches +- update of %%description +- disable valgrind for certain test-cases (libssh2 problem) + +* Tue May 25 2010 Kamil Dudka 7.20.1-6 +- fix -J/--remote-header-name to strip CR-LF (upstream patch) + +* Wed Apr 28 2010 Kamil Dudka 7.20.1-5 +- CRL support now works again (#581926) +- make it possible to start a testing OpenSSH server when building with SELinux + in the enforcing mode (#521087) + +* Sat Apr 24 2010 Kamil Dudka 7.20.1-4 +- upstream patch preventing failure of test536 with threaded DNS resolver +- upstream patch preventing SSL handshake timeout underflow + +* Thu Apr 22 2010 Paul Howarth 7.20.1-3 +- replace Rawhide s390-sleep patch with a more targeted patch adding a + delay after tests 513 and 514 rather than after all tests + +* Wed Apr 21 2010 Kamil Dudka 7.20.1-2 +- experimentally enabled threaded DNS lookup +- make curl-config multilib ready again (#584107) + +* Mon Apr 19 2010 Kamil Dudka 7.20.1-1 +- new upstream release + +* Tue Mar 23 2010 Kamil Dudka 7.20.0-4 +- add missing quote in libcurl.m4 (#576252) + +* Fri Mar 19 2010 Kamil Dudka 7.20.0-3 +- throw CURLE_SSL_CERTPROBLEM in case peer rejects a certificate (#565972) +- valgrind temporarily disabled (#574889) +- kerberos installation prefix has been changed + +* Wed Feb 24 2010 Kamil Dudka 7.20.0-2 +- exclude test1112 from the test suite (#565305) + +* Thu Feb 11 2010 Kamil Dudka 7.20.0-1 +- new upstream release - added support for IMAP(S), POP3(S), SMTP(S) and RTSP +- dropped patches applied upstream +- dropped curl-7.16.0-privlibs.patch no longer useful +- a new patch forcing -lrt when linking the curl tool and test-cases + +* Fri Jan 29 2010 Kamil Dudka 7.19.7-11 +- upstream patch adding a new option -J/--remote-header-name +- dropped temporary workaround for #545779 + +* Thu Jan 14 2010 Chris Weyl 7.19.7-10 +- bump for libssh2 rebuild + +* Sun Dec 20 2009 Kamil Dudka 7.19.7-9 +- temporary workaround for #548269 + (restored behavior of 7.19.7-4) + +* Wed Dec 09 2009 Kamil Dudka 7.19.7-8 +- replace hard wired port numbers in the test suite + +* Wed Dec 09 2009 Kamil Dudka 7.19.7-7 +- use different port numbers for 32bit and 64bit builds +- temporary workaround for #545779 + +* Tue Dec 08 2009 Kamil Dudka 7.19.7-6 +- make it possible to run test241 +- re-enable SCP/SFTP tests (#539444) + +* Sat Dec 05 2009 Kamil Dudka 7.19.7-5 +- avoid use of uninitialized value in lib/nss.c +- suppress failure of test513 on s390 + +* Tue Dec 01 2009 Kamil Dudka 7.19.7-4 +- do not require valgrind on s390 and s390x +- temporarily disabled SCP/SFTP test-suite (#539444) + +* Thu Nov 12 2009 Kamil Dudka 7.19.7-3 +- fix crash on doubly closed NSPR descriptor, patch contributed + by Kevin Baughman (#534176) +- new version of patch for broken TLS servers (#525496, #527771) + +* Wed Nov 04 2009 Kamil Dudka 7.19.7-2 +- increased release number (CVS problem) + +* Wed Nov 04 2009 Kamil Dudka 7.19.7-1 +- new upstream release, dropped applied patches +- workaround for broken TLS servers (#525496, #527771) + +* Wed Oct 14 2009 Kamil Dudka 7.19.6-13 +- fix timeout issues and gcc warnings within lib/nss.c + +* Tue Oct 06 2009 Kamil Dudka 7.19.6-12 +- upstream patch for NSS support written by Guenter Knauf + +* Wed Sep 30 2009 Kamil Dudka 7.19.6-11 +- build libcurl with c-ares support (#514771) + +* Sun Sep 27 2009 Kamil Dudka 7.19.6-10 +- require libssh2>=1.2 properly (#525002) + +* Sat Sep 26 2009 Kamil Dudka 7.19.6-9 +- let curl test-suite use valgrind +- require libssh2>=1.2 (#525002) + +* Mon Sep 21 2009 Chris Weyl - 7.19.6-8 +- rebuild for libssh2 1.2 + +* Thu Sep 17 2009 Kamil Dudka 7.19.6-7 +- make curl test-suite more verbose + +* Wed Sep 16 2009 Kamil Dudka 7.19.6-6 +- update polling patch to the latest upstream version + +* Thu Sep 03 2009 Kamil Dudka 7.19.6-5 +- cover ssh and stunnel support by the test-suite + +* Wed Sep 02 2009 Kamil Dudka 7.19.6-4 +- use pkg-config to find nss and libssh2 if possible +- better patch (not only) for SCP/SFTP polling +- improve error message for not matching common name (#516056) + +* Fri Aug 21 2009 Kamil Dudka 7.19.6-3 +- avoid tight loop during a sftp upload +- http://permalink.gmane.org/gmane.comp.web.curl.library/24744 + +* Tue Aug 18 2009 Kamil Dudka 7.19.6-2 +- let curl package depend on the same version of libcurl + +* Fri Aug 14 2009 Kamil Dudka 7.19.6-1 +- new upstream release, dropped applied patches +- changed NSS code to not ignore the value of ssl.verifyhost and produce more + verbose error messages (#516056) + +* Wed Aug 12 2009 Ville Skyttä - 7.19.5-10 +- Use lzma compressed upstream tarball. + +* Fri Jul 24 2009 Fedora Release Engineering - 7.19.5-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Wed Jul 22 2009 Kamil Dudka 7.19.5-8 +- do not pre-login to all PKCS11 slots, it causes problems with HW tokens +- try to select client certificate automatically when not specified, thanks + to Claes Jakobsson + +* Fri Jul 10 2009 Kamil Dudka 7.19.5-7 +- fix SIGSEGV when using NSS client certificates, thanks to Claes Jakobsson + +* Sun Jul 05 2009 Kamil Dudka 7.19.5-6 +- force test suite to use the just built libcurl, thanks to Paul Howarth + +* Thu Jul 02 2009 Kamil Dudka 7.19.5-5 +- run test suite after build +- enable built-in manual + +* Wed Jun 24 2009 Kamil Dudka 7.19.5-4 +- fix bug introduced by the last build (#504857) + +* Wed Jun 24 2009 Kamil Dudka 7.19.5-3 +- exclude curlbuild.h content from spec (#504857) + +* Wed Jun 10 2009 Kamil Dudka 7.19.5-2 +- avoid unguarded comparison in the spec file, thanks to R P Herrold (#504857) + +* Tue May 19 2009 Kamil Dudka 7.19.5-1 +- update to 7.19.5, dropped applied patches + +* Mon May 11 2009 Kamil Dudka 7.19.4-11 +- fix infinite loop while loading a private key, thanks to Michael Cronenworth + (#453612) + +* Mon Apr 27 2009 Kamil Dudka 7.19.4-10 +- fix curl/nss memory leaks while using client certificate (#453612, accepted + by upstream) + +* Wed Apr 22 2009 Kamil Dudka 7.19.4-9 +- add missing BuildRequire for autoconf + +* Wed Apr 22 2009 Kamil Dudka 7.19.4-8 +- fix configure.ac to not discard -g in CFLAGS (#496778) + +* Tue Apr 21 2009 Debarshi Ray 7.19.4-7 +- Fixed configure to respect the environment's CFLAGS and CPPFLAGS settings. + +* Tue Apr 14 2009 Kamil Dudka 7.19.4-6 +- upstream patch fixing memory leak in lib/nss.c (#453612) +- remove redundant dependency of libcurl-devel on libssh2-devel + +* Wed Mar 18 2009 Kamil Dudka 7.19.4-5 +- enable 6 additional crypto algorithms by default (#436781, + accepted by upstream) + +* Thu Mar 12 2009 Kamil Dudka 7.19.4-4 +- fix memory leak in src/main.c (accepted by upstream) +- avoid using %%ifarch + +* Wed Mar 11 2009 Kamil Dudka 7.19.4-3 +- make libcurl-devel multilib-ready (bug #488922) + +* Fri Mar 06 2009 Jindrich Novy 7.19.4-2 +- drop .easy-leak patch, causes problems in pycurl (#488791) +- fix libcurl-devel dependencies (#488895) + +* Tue Mar 03 2009 Jindrich Novy 7.19.4-1 +- update to 7.19.4 (fixes CVE-2009-0037) +- fix leak in curl_easy* functions, thanks to Kamil Dudka +- drop nss-fix patch, applied upstream + +* Tue Feb 24 2009 Fedora Release Engineering - 7.19.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Tue Feb 17 2009 Kamil Dudka 7.19.3-1 +- update to 7.19.3, dropped applied nss patches +- add patch fixing 7.19.3 curl/nss bugs + +* Mon Dec 15 2008 Jindrich Novy 7.18.2-9 +- rebuild for f10/rawhide cvs tag clashes + +* Sat Dec 06 2008 Jindrich Novy 7.18.2-8 +- use improved NSS patch, thanks to Rob Crittenden (#472489) + +* Tue Sep 09 2008 Jindrich Novy 7.18.2-7 +- update the thread safety patch, thanks to Rob Crittenden (#462217) + +* Wed Sep 03 2008 Warren Togami 7.18.2-6 +- add thread safety to libcurl NSS cleanup() functions (#459297) + +* Fri Aug 22 2008 Tom "spot" Callaway 7.18.2-5 +- undo mini libcurl.so.3 + +* Mon Aug 11 2008 Tom "spot" Callaway 7.18.2-4 +- make miniature library for libcurl.so.3 + +* Fri Jul 4 2008 Jindrich Novy 7.18.2-3 +- enable support for libssh2 (#453958) + +* Wed Jun 18 2008 Jindrich Novy 7.18.2-2 +- fix curl_multi_perform() over a proxy (#450140), thanks to + Rob Crittenden + +* Wed Jun 4 2008 Jindrich Novy 7.18.2-1 +- update to 7.18.2 + +* Wed May 7 2008 Jindrich Novy 7.18.1-2 +- spec cleanup, thanks to Paul Howarth (#225671) + - drop BR: libtool + - convert CHANGES and README to UTF-8 + - _GNU_SOURCE in CFLAGS is no more needed + - remove bogus rpath + +* Mon Mar 31 2008 Jindrich Novy 7.18.1-1 +- update to curl 7.18.1 (fixes #397911) +- add ABI docs for libcurl +- remove --static-libs from curl-config +- drop curl-config patch, obsoleted by @SSL_ENABLED@ autoconf + substitution (#432667) + +* Fri Feb 15 2008 Jindrich Novy 7.18.0-2 +- define _GNU_SOURCE so that NI_MAXHOST gets defined from glibc + +* Mon Jan 28 2008 Jindrich Novy 7.18.0-1 +- update to curl-7.18.0 +- drop sslgen patch -> applied upstream +- fix typo in description + +* Tue Jan 22 2008 Jindrich Novy 7.17.1-6 +- fix curl-devel obsoletes so that we don't break F8->F9 upgrade + path (#429612) + +* Tue Jan 8 2008 Jindrich Novy 7.17.1-5 +- do not attempt to close a bad socket (#427966), + thanks to Caolan McNamara + +* Tue Dec 4 2007 Jindrich Novy 7.17.1-4 +- rebuild because of the openldap soname bump +- remove old nsspem patch + +* Fri Nov 30 2007 Jindrich Novy 7.17.1-3 +- drop useless ldap library detection since curl doesn't + dlopen()s it but links to it -> BR: openldap-devel +- enable LDAPS support (#225671), thanks to Paul Howarth +- BR: krb5-devel to reenable GSSAPI support +- simplify build process +- update description + +* Wed Nov 21 2007 Jindrich Novy 7.17.1-2 +- update description to contain complete supported servers list (#393861) + +* Sat Nov 17 2007 Jindrich Novy 7.17.1-1 +- update to curl 7.17.1 +- include patch to enable SSL usage in NSS when a socket is opened + nonblocking, thanks to Rob Crittenden (rcritten@redhat.com) + +* Wed Oct 24 2007 Jindrich Novy 7.16.4-10 +- correctly provide/obsolete curl-devel (#130251) + +* Wed Oct 24 2007 Jindrich Novy 7.16.4-9 +- create libcurl and libcurl-devel subpackages (#130251) + +* Thu Oct 11 2007 Jindrich Novy 7.16.4-8 +- list features correctly when curl is compiled against NSS (#316191) + +* Mon Sep 17 2007 Jindrich Novy 7.16.4-7 +- add zlib-devel BR to enable gzip compressed transfers in curl (#292211) + +* Mon Sep 10 2007 Jindrich Novy 7.16.4-6 +- provide webclient (#225671) + +* Thu Sep 6 2007 Jindrich Novy 7.16.4-5 +- add support for the NSS PKCS#11 pem reader so the command-line is the + same for both OpenSSL and NSS by Rob Crittenden (rcritten@redhat.com) +- switch to NSS again + +* Mon Sep 3 2007 Jindrich Novy 7.16.4-4 +- revert back to use OpenSSL (#266021) + +* Mon Aug 27 2007 Jindrich Novy 7.16.4-3 +- don't use openssl, use nss instead + +* Fri Aug 10 2007 Jindrich Novy 7.16.4-2 +- fix anonymous ftp login (#251570), thanks to David Cantrell + +* Wed Jul 11 2007 Jindrich Novy 7.16.4-1 +- update to 7.16.4 + +* Mon Jun 25 2007 Jindrich Novy 7.16.3-1 +- update to 7.16.3 +- drop .print patch, applied upstream +- next series of merge review fixes by Paul Howarth +- remove aclocal stuff, no more needed +- simplify makefile arguments +- don't reference standard library paths in libcurl.pc +- include docs/CONTRIBUTE + +* Mon Jun 18 2007 Jindrich Novy 7.16.2-5 +- don't print like crazy (#236981), backported from upstream CVS + +* Fri Jun 15 2007 Jindrich Novy 7.16.2-4 +- another series of review fixes (#225671), + thanks to Paul Howarth +- check version of ldap library automatically +- don't use %%makeinstall and preserve timestamps +- drop useless patches + +* Fri May 11 2007 Jindrich Novy 7.16.2-3 +- add automake BR to curl-devel to fix aclocal dir. ownership, + thanks to Patrice Dumas + +* Thu May 10 2007 Jindrich Novy 7.16.2-2 +- package libcurl.m4 in curl-devel (#239664), thanks to Quy Tonthat + +* Wed Apr 11 2007 Jindrich Novy 7.16.2-1 +- update to 7.16.2 + +* Mon Feb 19 2007 Jindrich Novy 7.16.1-3 +- don't create/ship static libraries (#225671) + +* Mon Feb 5 2007 Jindrich Novy 7.16.1-2 +- merge review related spec fixes (#225671) + +* Mon Jan 29 2007 Jindrich Novy 7.16.1-1 +- update to 7.16.1 + +* Tue Jan 16 2007 Jindrich Novy 7.16.0-5 +- don't package generated makefiles for docs/examples to avoid + multilib conflicts + +* Mon Dec 18 2006 Jindrich Novy 7.16.0-4 +- convert spec to UTF-8 +- don't delete BuildRoot in %%prep phase +- rpmlint fixes + +* Thu Nov 16 2006 Jindrich Novy -7.16.0-3 +- prevent curl from dlopen()ing missing ldap libraries so that + ldap:// requests work (#215928) + +* Tue Oct 31 2006 Jindrich Novy - 7.16.0-2 +- fix BuildRoot +- add Requires: pkgconfig for curl-devel +- move LDFLAGS and LIBS to Libs.private in libcurl.pc.in (#213278) + +* Mon Oct 30 2006 Jindrich Novy - 7.16.0-1 +- update to curl-7.16.0 + +* Thu Aug 24 2006 Jindrich Novy - 7.15.5-1.fc6 +- update to curl-7.15.5 +- use %%{?dist} + +* Fri Jun 30 2006 Ivana Varekova - 7.15.4-1 +- update to 7.15.4 + +* Mon Mar 20 2006 Ivana Varekova - 7.15.3-1 +- fix multilib problem using pkg-config +- update to 7.15.3 + +* Thu Feb 23 2006 Ivana Varekova - 7.15.1-2 +- fix multilib problem - #181290 - + curl-devel.i386 not installable together with curl-devel.x86-64 + +* Fri Feb 10 2006 Jesse Keating - 7.15.1-1.2.1 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 7.15.1-1.2 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Thu Dec 8 2005 Ivana Varekova 7.15.1-1 +- update to 7.15.1 (bug 175191) + +* Wed Nov 30 2005 Ivana Varekova 7.15.0-3 +- fix curl-config bug 174556 - missing vernum value + +* Wed Nov 9 2005 Ivana Varekova 7.15.0-2 +- rebuilt + +* Tue Oct 18 2005 Ivana Varekova 7.15.0-1 +- update to 7.15.0 + +* Thu Oct 13 2005 Ivana Varekova 7.14.1-1 +- update to 7.14.1 + +* Thu Jun 16 2005 Ivana Varekova 7.14.0-1 +- rebuild new version + +* Tue May 03 2005 Ivana Varekova 7.13.1-3 +- fix bug 150768 - curl-7.12.3-2 breaks basic authentication + used Daniel Stenberg patch + +* Mon Apr 25 2005 Joe Orton 7.13.1-2 +- update to use ca-bundle in /etc/pki +- mark License as MIT not MPL + +* Wed Mar 9 2005 Ivana Varekova 7.13.1-1 +- rebuilt (7.13.1) + +* Tue Mar 1 2005 Tomas Mraz 7.13.0-2 +- rebuild with openssl-0.9.7e + +* Sun Feb 13 2005 Florian La Roche +- 7.13.0 + +* Wed Feb 9 2005 Joe Orton 7.12.3-3 +- don't pass /usr to --with-libidn to remove "-L/usr/lib" from + 'curl-config --libs' output on x86_64. + +* Fri Jan 28 2005 Adrian Havill 7.12.3-1 +- Upgrade to 7.12.3, which uses poll() for FDSETSIZE limit (#134794) +- require libidn-devel for devel subpkg (#141341) +- remove proftpd kludge; included upstream + +* Wed Oct 06 2004 Adrian Havill 7.12.1-1 +- upgrade to 7.12.1 +- enable GSSAPI auth (#129353) +- enable I18N domain names (#134595) +- workaround for broken ProFTPD SSL auth (#134133). Thanks to + Aleksandar Milivojevic + +* Wed Sep 29 2004 Adrian Havill 7.12.0-4 +- move new docs position so defattr gets applied + +* Mon Sep 27 2004 Warren Togami 7.12.0-3 +- remove INSTALL, move libcurl docs to -devel + +* Mon Jul 26 2004 Jindrich Novy +- updated to 7.12.0 +- updated nousr patch + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Wed Apr 07 2004 Adrian Havill 7.11.1-1 +- upgraded; updated nousr patch +- added COPYING (#115956) +- + +* Tue Mar 02 2004 Elliot Lee +- rebuilt + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Sat Jan 31 2004 Florian La Roche +- update to 7.10.8 +- remove patch2, already upstream + +* Wed Oct 15 2003 Adrian Havill 7.10.6-7 +- aclocal before libtoolize +- move OpenLDAP license so it's present as a doc file, present in + both the source and binary as per conditions + +* Mon Oct 13 2003 Adrian Havill 7.10.6-6 +- add OpenLDAP copyright notice for usage of code, add OpenLDAP + license for this code + +* Tue Oct 07 2003 Adrian Havill 7.10.6-5 +- match serverAltName certs with SSL (#106168) + +* Tue Sep 16 2003 Adrian Havill 7.10.6-4.1 +- bump n-v-r for RHEL + +* Tue Sep 16 2003 Adrian Havill 7.10.6-4 +- restore ca cert bundle (#104400) +- require openssl, we want to use its ca-cert bundle + +* Sun Sep 7 2003 Joe Orton 7.10.6-3 +- rebuild + +* Fri Sep 5 2003 Joe Orton 7.10.6-2.2 +- fix to include libcurl.so + +* Mon Aug 25 2003 Adrian Havill 7.10.6-2.1 +- bump n-v-r for RHEL + +* Mon Aug 25 2003 Adrian Havill 7.10.6-2 +- devel subpkg needs openssl-devel as a Require (#102963) + +* Mon Jul 28 2003 Adrian Havill 7.10.6-1 +- bumped version + +* Tue Jul 01 2003 Adrian Havill 7.10.5-1 +- bumped version + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Sat Apr 12 2003 Florian La Roche +- update to 7.10.4 +- adapt nousr patch + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Tue Jan 21 2003 Joe Orton 7.9.8-4 +- don't add -L/usr/lib to 'curl-config --libs' output + +* Tue Jan 7 2003 Nalin Dahyabhai 7.9.8-3 +- rebuild + +* Wed Nov 6 2002 Joe Orton 7.9.8-2 +- fix `curl-config --libs` output for libdir!=/usr/lib +- remove docs/LIBCURL from docs list; remove unpackaged libcurl.la +- libtoolize and reconf + +* Mon Jul 22 2002 Trond Eivind Glomsrød 7.9.8-1 +- 7.9.8 (# 69473) + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Sun May 26 2002 Tim Powers +- automated rebuild + +* Thu May 16 2002 Trond Eivind Glomsrød 7.9.7-1 +- 7.9.7 + +* Wed Apr 24 2002 Trond Eivind Glomsrød 7.9.6-1 +- 7.9.6 + +* Thu Mar 21 2002 Trond Eivind Glomsrød 7.9.5-2 +- Stop the curl-config script from printing -I/usr/include + and -L/usr/lib (#59497) + +* Fri Mar 8 2002 Trond Eivind Glomsrød 7.9.5-1 +- 7.9.5 + +* Tue Feb 26 2002 Trond Eivind Glomsrød 7.9.3-2 +- Rebuild + +* Wed Jan 23 2002 Nalin Dahyabhai 7.9.3-1 +- update to 7.9.3 + +* Wed Jan 09 2002 Tim Powers 7.9.2-2 +- automated rebuild + +* Wed Jan 9 2002 Trond Eivind Glomsrød 7.9.2-1 +- 7.9.2 + +* Fri Aug 17 2001 Nalin Dahyabhai +- include curl-config in curl-devel +- update to 7.8 to fix memory leak and strlcat() symbol pollution from libcurl + +* Wed Jul 18 2001 Crutcher Dunnavant +- added openssl-devel build req + +* Mon May 21 2001 Tim Powers +- built for the distro + +* Tue Apr 24 2001 Jeff Johnson +- upgrade to curl-7.7.2. +- enable IPv6. + +* Fri Mar 2 2001 Tim Powers +- rebuilt against openssl-0.9.6-1 + +* Thu Jan 4 2001 Tim Powers +- fixed mising ldconfigs +- updated to 7.5.2, bug fixes + +* Mon Dec 11 2000 Tim Powers +- updated to 7.5.1 + +* Mon Nov 6 2000 Tim Powers +- update to 7.4.1 to fix bug #20337, problems with curl -c +- not using patch anymore, it's included in the new source. Keeping + for reference + +* Fri Oct 20 2000 Nalin Dahyabhai +- fix bogus req in -devel package + +* Fri Oct 20 2000 Tim Powers +- devel package needed defattr so that root owns the files + +* Mon Oct 16 2000 Nalin Dahyabhai +- update to 7.3 +- apply vsprintf/vsnprintf patch from Colin Phipps via Debian + +* Mon Aug 21 2000 Nalin Dahyabhai +- enable SSL support +- fix packager tag +- move buildroot to %%{_tmppath} + +* Tue Aug 1 2000 Tim Powers +- fixed vendor tag for bug #15028 + +* Mon Jul 24 2000 Prospector +- rebuilt + +* Tue Jul 11 2000 Tim Powers +- workaround alpha build problems with optimizations + +* Mon Jul 10 2000 Tim Powers +- rebuilt + +* Mon Jun 5 2000 Tim Powers +- put man pages in correct place +- use %%makeinstall + +* Mon Apr 24 2000 Tim Powers +- updated to 6.5.2 + +* Wed Nov 3 1999 Tim Powers +- updated sources to 6.2 +- gzip man page + +* Mon Aug 30 1999 Tim Powers +- changed group + +* Thu Aug 26 1999 Tim Powers +- changelog started +- general cleanups, changed prefix to /usr, added manpage to files section +- including in Powertools