diff --git a/SOURCES/0022-curl-7.29.0-24c3cdce.patch b/SOURCES/0022-curl-7.29.0-24c3cdce.patch
index 5dac548..7ed2377 100644
--- a/SOURCES/0022-curl-7.29.0-24c3cdce.patch
+++ b/SOURCES/0022-curl-7.29.0-24c3cdce.patch
@@ -1,7 +1,7 @@
 From ca7b1cd659eb0eb0ef355e3e122742abcea73287 Mon Sep 17 00:00:00 2001
 From: Kamil Dudka <kdudka@redhat.com>
 Date: Wed, 2 Jul 2014 16:34:48 +0200
-Subject: [PATCH 1/2] tool: call PR_Cleanup() on exit if NSPR is used
+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
@@ -48,7 +48,7 @@ index 95e9cc7..6a1ed6c 100644
 From 295471f8122cf6522c36f8e3588e5b4d15a691ea Mon Sep 17 00:00:00 2001
 From: Alessandro Ghedini <alessandro@ghedini.me>
 Date: Thu, 17 Jul 2014 14:37:28 +0200
-Subject: [PATCH 2/2] build: link curl to NSS libraries when NSS support is
+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
@@ -140,3 +140,98 @@ index 41fb549..1b578c2 100644
 -- 
 2.1.0
 
+
+From 0631da3859c9868ff317521544a246b5be83e600 Mon Sep 17 00:00:00 2001
+From: Kamil Dudka <kdudka@redhat.com>
+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 <kdudka@redhat.com>
+---
+ 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 <locale.h> /* for setlocale() */
+ #endif
+ 
++#ifdef USE_NSS
++#include <nspr.h>
++#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/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 <daniel@haxx.se>
+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 <kdudka@redhat.com>
+---
+ 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	
+ </file>
+ </client>
+@@ -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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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,        /* <username>, if used */
+   STRING_PASSWORD,        /* <password>, if used */
++  STRING_OPTIONS,         /* <options>, if used */
+   STRING_PROXYUSERNAME,   /* Proxy <username>, if used */
+   STRING_PROXYPASSWORD,   /* Proxy <password>, 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <kdudka@redhat.com>
+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 <kdudka@redhat.com>
+---
+ 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 <yangsita@gmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <yangsita@gmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <jrnieder@gmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <jrnieder@gmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <jrnieder@gmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <jrnieder@gmail.com>
+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}' <out |
+	tr -d '\r' |
+	base64 -d
+  )
+  password=${userpass#me:}
+  echo ${#password}
+
+Expected result: 300
+Actual result: 255
+
+The fix is simple: allocate appropriately sized buffers on the heap
+instead of trying to squeeze the provided values into fixed-size
+on-stack buffers.
+
+Bug: http://bugs.debian.org/719856
+Reported-by: Colby Ranger
+
+Upstream-commit: 15f76bf7bb92b315799541b0e5127c8d22a50733
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ 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 <jrnieder@gmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <jrnieder@gmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <daniel@haxx.se>
+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 <daniel@haxx.se>
+
+Upstream-commit: 169fedbdce93ecf14befb6e0e1ce6a2d480252a3
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ 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
+  </name>
+  <command>
+-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'
+ </command>
+ </client>
+ 
+@@ -65,7 +65,7 @@ Proxy-Connection: Keep-Alive
+ </proxy>
+ <protocol>
+ 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 <dan@coneharvesters.com>
+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 <kdudka@redhat.com>
+---
+ 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 <peter@lekensteyn.nl>
+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 <peter@lekensteyn.nl>
+
+Upstream-commit: cf6c5c222d86088cbfc9dee4c23f8ada96ee91e7
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ 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 <steve_holme@hotmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <peter@lekensteyn.nl>
+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 <peter@lekensteyn.nl>
+
+Upstream-commit: fb7d7e0022f22035449bbc506068004f0568f8ae
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ 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 <peter@lekensteyn.nl>
+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 <peter@lekensteyn.nl>
+
+Upstream-commit: e9c7a86220ddf4e67b8bff56cddfc7388afcc9ef
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ 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, <daniel@haxx.se>, et al.
++ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
+  *
+  * This software is licensed as described in the file COPYING, which
+  * you should have received as part of this distribution. The terms
+@@ -23,12 +23,19 @@
+  ***************************************************************************/
+ #include "server_setup.h"
+ 
++#ifdef HAVE_SYS_UN_H
++#include <sys/un.h> /* 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 <peter@lekensteyn.nl>
+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 <peter@lekensteyn.nl>
+
+Upstream-commit: f1cc2a2c0cf8e191e606c6093c679fbee95e8809
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ 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.
+ </server>
+@@ -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 <server> name. This works even if IPv6 support isn't
++            # IPv6 <server> 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 <features> 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 <peter@lekensteyn.nl>
+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 <peter@lekensteyn.nl>
+
+Upstream-commit: 479abdd32eee15dab78d0cd6b1786d569680f0ac
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ 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 @@
++<testcase>
++<info>
++<keywords>
++HTTP
++HTTP GET
++unix sockets
++</keywords>
++</info>
++
++<reply>
++<data>
++HTTP/1.1 200 OK
++Date: Sun, 16 Nov 2014 23:47:38 GMT
++Content-Length: 17
++
++Based on test300
++</data>
++</reply>
++
++<client>
++<features>
++unix-sockets
++</features>
++<server>
++http-unix
++</server>
++ <name>
++simple HTTP GET over UNIX socket
++ </name>
++ <command>
++--unix-socket %HTTPUNIXPATH http://server-interpreted.example.com/1435
++</command>
++</client>
++
++<verify>
++<strip>
++^User-Agent:.*
++</strip>
++<protocol>
++GET /1435 HTTP/1.1
++Host: server-interpreted.example.com
++Accept: */*
++
++</protocol>
++</verify>
++</testcase>
+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 @@
++<testcase>
++<info>
++<keywords>
++HTTP
++HTTP GET
++unix sockets
++</keywords>
++</info>
++
++<reply>
++<data1>
++HTTP/1.1 200 OK
++Date: Mon, 17 Nov 2014 13:42:47 GMT
++Content-Length: 6
++
++First
++</data1>
++<data2>
++HTTP/1.1 200 OK
++Date: Mon, 17 Nov 2014 13:42:48 GMT
++Content-Length: 7
++
++Second
++</data2>
++<data3>
++HTTP/1.1 200 OK
++Date: Mon, 17 Nov 2014 13:42:49 GMT
++Content-Length: 6
++
++Third
++</data3>
++</reply>
++
++<client>
++<features>
++unix-sockets
++</features>
++<server>
++http-unix
++</server>
++ <name>
++HTTP requests with multiple connections over UNIX socket
++ </name>
++ <command>
++--unix-socket %HTTPUNIXPATH http://one.example.com/14360001 http://two.example.com/14360002 http://one.example.com/14360003
++</command>
++</client>
++
++<verify>
++<strip>
++^User-Agent:.*
++</strip>
++<protocol>
++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: */*
++
++</protocol>
++<stdout>
++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
++</stdout>
++</verify>
++</testcase>
+-- 
+2.5.2
+
+
+From f784b2d3d6cf08193662a23aae9305f11c4a4559 Mon Sep 17 00:00:00 2001
+From: Peter Wu <peter@lekensteyn.nl>
+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 <peter@lekensteyn.nl>
+
+Upstream-commit: 970c22f970f0172e6a4c98ccc3176c740ddaa1c6
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ 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 <sys/un.h>
++
++"
++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 <sys/un.h>
++  ])
++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 <arpa/inet.h>
+ #endif
++#ifdef HAVE_SYS_UN_H
++#  include <sys/un.h>
++#endif
+ 
+ #ifdef __VMS
+ #  include <in.h>
+@@ -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 <inet.h>
+ #endif
+ 
++#ifdef HAVE_SYS_UN_H
++#include <sys/un.h>
++#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 <password> */
+ #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 <peter@lekensteyn.nl>
+Date: Thu, 27 Nov 2014 23:59:26 +0100
+Subject: [PATCH 08/11] tool: add --unix-socket option
+
+Signed-off-by: Peter Wu <peter@lekensteyn.nl>
+
+Upstream-commit: c8644d1f638fdd8f4bf34fe64e910ba704fb26c0
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ 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 <daniel@haxx.se>
+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 <kdudka@redhat.com>
+---
+ 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 <path>"
++(HTTP) Connect through this UNIX domain socket, instead of using the
++network. (Added in 7.40.0)
+ .IP "-u, --user <user:password>"
+ 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 <daniel@haxx.se>
+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 <kdudka@redhat.com>
+---
+ 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 <peter@lekensteyn.nl>
+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 <peter@lekensteyn.nl>
+
+Upstream-commit: 2e557de09431854e4ad137cd741a582caa917517
+Signed-off-by: Kamil Dudka <kdudka@redhat.com>
+---
+ 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 <jjlin@cs.stanford.edu>
+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 <kdudka@redhat.com>
+---
+ 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 <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 <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 <kdudka@redhat.com>
+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 <kdudka@redhat.com>
+---
+ 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 <kdudka@redhat.com>
+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 <kdudka@redhat.com>
+---
+ 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 <kdudka@redhat.com>
+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 <kdudka@redhat.com>
+---
+ 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 <kdudka@redhat.com>
+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 <kdudka@redhat.com>
+---
+ 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 <URL>"
+-- 
+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 <daniel@haxx.se>
+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 <kdudka@redhat.com>
+---
+ 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 <turnaev.e@gmail.com>
+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 <kdudka@redhat.com>
+---
+ 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 <daniel@haxx.se>
+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 <kdudka@redhat.com>
+---
+ 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 <kdudka@redhat.com>
+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 <kdudka@redhat.com>
+---
+ 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 <curl@paulsd.com>
+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 <kdudka@redhat.com>
+---
+ 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 <daniel@haxx.se>
+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 <kdudka@redhat.com>
+---
+ 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 <daniel@haxx.se>
+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 <kdudka@redhat.com>
+---
+ 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 <kdudka@redhat.com>
+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 <kdudka@redhat.com>
+---
+ 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/0102-curl-7.29.0-debug.patch b/SOURCES/0102-curl-7.29.0-debug.patch
index 7f70530..090afdb 100644
--- a/SOURCES/0102-curl-7.29.0-debug.patch
+++ b/SOURCES/0102-curl-7.29.0-debug.patch
@@ -12,7 +12,7 @@ diff --git a/configure b/configure
 index 8f079a3..53b4774 100755
 --- a/configure
 +++ b/configure
-@@ -15759,18 +15759,11 @@ $as_echo "yes" >&6; }
+@@ -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`
diff --git a/SPECS/curl.spec b/SPECS/curl.spec
index 122a47a..e591f0c 100644
--- a/SPECS/curl.spec
+++ b/SPECS/curl.spec
@@ -1,7 +1,7 @@
 Summary: A utility for getting files from remote servers (FTP, HTTP, and others)
 Name: curl
 Version: 7.29.0
-Release: 25%{?dist}
+Release: 35%{?dist}
 License: MIT
 Group: Applications/Internet
 Source: http://curl.haxx.se/download/%{name}-%{version}.tar.lzma
@@ -106,6 +106,36 @@ 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
+
 # patch making libcurl multilib ready
 Patch101: 0101-curl-7.29.0-multilib.patch
 
@@ -254,6 +284,13 @@ documentation of the library, too.
 %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
@@ -264,24 +301,24 @@ documentation of the library, too.
 %patch107 -p1
 %patch108 -p1
 
+# upstream patches
+%patch41 -p1
+%patch42 -p1
+%patch43 -p1
+
 # replace hard wired port numbers in the test suite
 cd tests/data/
 sed -i s/899\\\([0-9]\\\)/%{?__isa_bits}9\\1/ test*
 cd -
 
-# disable test 1112 (#565305)
-printf "1112\n" >> tests/data/DISABLED
+# 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
 
-#skip 2 test from CentOS
-echo "46" >> tests/data/DISABLED
-echo "2032" >> tests/data/DISABLED
-#
-
 %build
 [ -x /usr/kerberos/bin/krb5-config ] && KRB5_PREFIX="=/usr/kerberos"
 %configure --disable-static \
@@ -377,8 +414,42 @@ rm -rf $RPM_BUILD_ROOT
 %{_datadir}/aclocal/libcurl.m4
 
 %changelog
-* Sun Nov 22 2015 Johnny Hughes <johnny@centos.org> 7.29.0-25
-- skip 2 failed tests on centos builds
+* Fri Aug 26 2016 Kamil Dudka <kdudka@redhat.com> 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 <kdudka@redhat.com> 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 <kdudka@redhat.com> 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 <kdudka@redhat.com> 7.29.0-32
+- configure: improve detection of GCC's -fvisibility= flag
+
+* Mon Jun 20 2016 Kamil Dudka <kdudka@redhat.com> 7.29.0-31
+- prevent curl_multi_wait() from missing an event (#1347904)
+
+* Tue Feb 16 2016 Kamil Dudka <kdudka@redhat.com> 7.29.0-30
+- curl.1: --disable-{eprt,epsv} are ignored for IPv6 hosts (#1305974)
+
+* Fri Jan 15 2016 Kamil Dudka <kdudka@redhat.com> 7.29.0-29
+- SSH: make CURLOPT_SSH_PUBLIC_KEYFILE treat "" as NULL (#1275769)
+
+* Mon Nov 02 2015 Kamil Dudka <kdudka@redhat.com> 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 <kdudka@redhat.com> 7.29.0-27
+- SSH: do not require public key file for user authentication (#1275769)
+
+* Tue Sep 08 2015 Kamil Dudka <kdudka@redhat.com> 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 <kdudka@redhat.com> 7.29.0-25
 - fix spurious failure of test 1500 on ppc64le (#1218272)