Commit a5aec587 authored by Steve Holme's avatar Steve Holme
Browse files

imap/pop3/smtp: Fixed connections upgraded with TLS are not reused

Regression since commit 710f14ed.

Bug: https://github.com/curl/curl/issues/422
Reported-by: Justin Ehlert
parent 307f3cf3
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -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 */
+9 −1
Original line number Diff line number Diff line
@@ -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 */
+9 −1
Original line number Diff line number Diff line
@@ -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 */
+121 −6
Original line number Diff line number Diff line
@@ -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
+1 −0
Original line number Diff line number Diff line
@@ -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 */