aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/imap.c10
-rw-r--r--lib/pop3.c10
-rw-r--r--lib/smtp.c10
-rw-r--r--lib/url.c127
-rw-r--r--lib/urldata.h1
5 files changed, 149 insertions, 9 deletions
diff --git a/lib/imap.c b/lib/imap.c
index c75ccf9ad..0339add48 100644
--- a/lib/imap.c
+++ b/lib/imap.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, 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
@@ -227,7 +227,11 @@ static const struct SASLproto saslimap = {
#ifdef USE_SSL
static void imap_to_imaps(struct connectdata *conn)
{
+ /* Change the connection handler */
conn->handler = &Curl_handler_imaps;
+
+ /* Set the connection's upgraded to TLS flag */
+ conn->tls_upgraded = TRUE;
}
#else
#define imap_to_imaps(x) Curl_nop_stmt
@@ -1738,6 +1742,10 @@ static CURLcode imap_setup_connection(struct connectdata *conn)
if(result)
return result;
+ /* Clear the TLS upgraded flag */
+ conn->tls_upgraded = FALSE;
+
+ /* Set up the proxy if necessary */
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel IMAP operations through the proxy, we
switch and use HTTP operations only */
diff --git a/lib/pop3.c b/lib/pop3.c
index 73e1cb2e4..cb53b7445 100644
--- a/lib/pop3.c
+++ b/lib/pop3.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, 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
@@ -225,7 +225,11 @@ static const struct SASLproto saslpop3 = {
#ifdef USE_SSL
static void pop3_to_pop3s(struct connectdata *conn)
{
+ /* Change the connection handler */
conn->handler = &Curl_handler_pop3s;
+
+ /* Set the connection's upgraded to TLS flag */
+ conn->tls_upgraded = TRUE;
}
#else
#define pop3_to_pop3s(x) Curl_nop_stmt
@@ -1354,6 +1358,10 @@ static CURLcode pop3_setup_connection(struct connectdata *conn)
if(result)
return result;
+ /* Clear the TLS upgraded flag */
+ conn->tls_upgraded = FALSE;
+
+ /* Set up the proxy if necessary */
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel POP3 operations through the proxy, we
switch and use HTTP operations only */
diff --git a/lib/smtp.c b/lib/smtp.c
index 7102ffbf3..2a87c6eae 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, 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
@@ -224,7 +224,11 @@ static const struct SASLproto saslsmtp = {
#ifdef USE_SSL
static void smtp_to_smtps(struct connectdata *conn)
{
+ /* Change the connection handler */
conn->handler = &Curl_handler_smtps;
+
+ /* Set the connection's upgraded to TLS flag */
+ conn->tls_upgraded = TRUE;
}
#else
#define smtp_to_smtps(x) Curl_nop_stmt
@@ -1450,6 +1454,10 @@ static CURLcode smtp_setup_connection(struct connectdata *conn)
struct SessionHandle *data = conn->data;
CURLcode result;
+ /* Clear the TLS upgraded flag */
+ conn->tls_upgraded = FALSE;
+
+ /* Set up the proxy if necessary */
if(conn->bits.httpproxy && !data->set.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel SMTP operations through the proxy, we
switch and use HTTP operations only */
diff --git a/lib/url.c b/lib/url.c
index 15bababbf..277c4cced 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -151,6 +151,8 @@ static CURLcode parse_url_login(struct SessionHandle *data,
static CURLcode parse_login_details(const char *login, const size_t len,
char **userptr, char **passwdptr,
char **optionsptr);
+static unsigned int get_protocol_family(unsigned int protocol);
+
/*
* Protocol table.
*/
@@ -3272,7 +3274,8 @@ ConnectionExists(struct SessionHandle *data,
if((needle->handler->flags&PROTOPT_SSL) !=
(check->handler->flags&PROTOPT_SSL))
/* don't do mixed SSL and non-SSL connections */
- if(!(needle->handler->protocol & check->handler->protocol))
+ if(get_protocol_family(check->handler->protocol) !=
+ needle->handler->protocol || !check->tls_upgraded)
/* except protocols that have been upgraded via TLS */
continue;
@@ -3327,14 +3330,16 @@ ConnectionExists(struct SessionHandle *data,
Curl_raw_equal(needle->proxy.name, check->proxy.name) &&
(needle->port == check->port))) {
/* The requested connection does not use a HTTP proxy or it uses SSL or
- it is a non-SSL protocol tunneled over the same http proxy name and
- port number or it is a non-SSL protocol which is allowed to be
- upgraded via TLS */
-
+ it is a non-SSL protocol tunneled over the same HTTP proxy name and
+ port number */
if((Curl_raw_equal(needle->handler->scheme, check->handler->scheme) ||
- needle->handler->protocol & check->handler->protocol) &&
+ (get_protocol_family(check->handler->protocol) ==
+ needle->handler->protocol && check->tls_upgraded)) &&
Curl_raw_equal(needle->host.name, check->host.name) &&
needle->remote_port == check->remote_port) {
+ /* The schemes match or the the protocol family is the same and the
+ previous connection was TLS upgraded, and the hostname and host
+ port match */
if(needle->handler->flags & PROTOPT_SSL) {
/* This is a SSL connection so verify that we're using the same
SSL options as well */
@@ -6362,3 +6367,113 @@ CURLcode Curl_do_more(struct connectdata *conn, int *complete)
return result;
}
+
+/*
+* get_protocol_family()
+*
+* This is used to return the protocol family for a given protocol.
+*
+* Parameters:
+*
+* protocol [in] - A single bit protocol identifier such as HTTP or HTTPS.
+*
+* Returns the family as a single bit protocol identifier.
+*/
+
+unsigned int get_protocol_family(unsigned int protocol)
+{
+ unsigned int family;
+
+ switch(protocol) {
+ case CURLPROTO_HTTP:
+ case CURLPROTO_HTTPS:
+ family = CURLPROTO_HTTP;
+ break;
+
+ case CURLPROTO_FTP:
+ case CURLPROTO_FTPS:
+ family = CURLPROTO_IMAP;
+ break;
+
+ case CURLPROTO_SCP:
+ family = CURLPROTO_SCP;
+ break;
+
+ case CURLPROTO_SFTP:
+ family = CURLPROTO_SFTP;
+ break;
+
+ case CURLPROTO_TELNET:
+ family = CURLPROTO_TELNET;
+ break;
+
+ case CURLPROTO_LDAP:
+ case CURLPROTO_LDAPS:
+ family = CURLPROTO_IMAP;
+ break;
+
+ case CURLPROTO_DICT:
+ family = CURLPROTO_DICT;
+ break;
+
+ case CURLPROTO_FILE:
+ family = CURLPROTO_FILE;
+ break;
+
+ case CURLPROTO_TFTP:
+ family = CURLPROTO_TFTP;
+ break;
+
+ case CURLPROTO_IMAP:
+ case CURLPROTO_IMAPS:
+ family = CURLPROTO_IMAP;
+ break;
+
+ case CURLPROTO_POP3:
+ case CURLPROTO_POP3S:
+ family = CURLPROTO_POP3;
+ break;
+
+ case CURLPROTO_SMTP:
+ case CURLPROTO_SMTPS:
+ family = CURLPROTO_SMTP;
+ break;
+
+ case CURLPROTO_RTSP:
+ family = CURLPROTO_RTSP;
+ break;
+
+ case CURLPROTO_RTMP:
+ case CURLPROTO_RTMPS:
+ family = CURLPROTO_RTMP;
+ break;
+
+ case CURLPROTO_RTMPT:
+ case CURLPROTO_RTMPTS:
+ family = CURLPROTO_RTMPT;
+ break;
+
+ case CURLPROTO_RTMPE:
+ family = CURLPROTO_RTMPE;
+ break;
+
+ case CURLPROTO_RTMPTE:
+ family = CURLPROTO_RTMPTE;
+ break;
+
+ case CURLPROTO_GOPHER:
+ family = CURLPROTO_GOPHER;
+ break;
+
+ case CURLPROTO_SMB:
+ case CURLPROTO_SMBS:
+ family = CURLPROTO_SMB;
+ break;
+
+ default:
+ family = 0;
+ break;
+ }
+
+ return family;
+} \ No newline at end of file
diff --git a/lib/urldata.h b/lib/urldata.h
index fcb17561d..f832ea886 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -921,6 +921,7 @@ struct connectdata {
struct ssl_connect_data ssl[2]; /* this is for ssl-stuff */
struct ssl_config_data ssl_config;
+ bool tls_upgraded;
struct ConnectBits bits; /* various state-flags for this connection */