Commit 338553ed authored by Patrick Monnerat's avatar Patrick Monnerat
Browse files

- Proper handling of STARTTLS on SMTP, taking CURLUSESSL_TRY into account.

- SMTP falls back to RFC821 HELO when EHLO fails (and SSL is not required).
- Use of true local host name (i.e.: via gethostname()) when available, as default argument to SMTP HELO/EHLO.
- Test case 804 for HELO fallback.
parent 2abcd132
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -6,6 +6,13 @@

                                  Changelog

Patrick Monnerat (22 Feb 2010)
- Proper handling of STARTTLS on SMTP, taking CURLUSESSL_TRY into account.
- SMTP falls back to RFC821 HELO when EHLO fails (and SSL is not required).
- Use of true local host name (i.e.: via gethostname()) when available, as
  default argument to SMTP HELO/EHLO.
- Test case 804 for HELO fallback.

Daniel Stenberg (20 Feb 2010)
- Fixed the SMTP compliance by making sure RCPT TO addresses are specified
  properly in angle brackets. Recipients provided with CURLOPT_MAIL_RCPT now
+3 −0
Original line number Diff line number Diff line
@@ -66,7 +66,10 @@ This document lists documents and standards used by curl.

  RFC 2818 - HTTP Over TLS (TLS is the successor to SSL)

  RFC 2821 - SMTP protocol

  RFC 2964 - Use of HTTP State Management

  RFC 2965 - HTTP State Management Mechanism. Cookies. Obsoletes RFC2109

  RFC 3207 - SMTP over TLS
+75 −16
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
 * KIND, either express or implied.
 *
 * RFC2821 SMTP protocol
 * RFC3207 SMTP over TLS
 *
 * $Id$
 ***************************************************************************/
@@ -228,6 +229,7 @@ static void state(struct connectdata *conn,
    "STOP",
    "SERVERGREET",
    "EHLO",
    "HELO",
    "STARTTLS",
    "MAIL",
    "RCPT",
@@ -253,11 +255,26 @@ static CURLcode smtp_state_ehlo(struct connectdata *conn)

  /* send EHLO */
  result = Curl_pp_sendf(&conn->proto.smtpc.pp, "EHLO %s", smtpc->domain);

  if(result)
    return result;

  state(conn, SMTP_EHLO);
  return CURLE_OK;
}

static CURLcode smtp_state_helo(struct connectdata *conn)
{
  CURLcode result;
  struct smtp_conn *smtpc = &conn->proto.smtpc;

  /* send HELO */
  result = Curl_pp_sendf(&conn->proto.smtpc.pp, "HELO %s", smtpc->domain);

  if(result)
    return result;

  state(conn, SMTP_HELO);
  return CURLE_OK;
}

@@ -278,10 +295,14 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
  struct SessionHandle *data = conn->data;
  (void)instate; /* no use for this yet */

  if(smtpcode != 'O') {
  if(smtpcode != 220) {
    if(data->set.ftp_ssl == CURLUSESSL_TRY)
      state(conn, SMTP_STOP);
    else {
      failf(data, "STARTTLS denied. %c", smtpcode);
      result = CURLE_LOGIN_DENIED;
    }
  }
  else {
    /* Curl_ssl_connect is BLOCKING */
    result = Curl_ssl_connect(conn, FIRSTSOCKET);
@@ -290,7 +311,6 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
      result = smtp_state_ehlo(conn);
    }
  }
  state(conn, SMTP_STOP);
  return result;
}

@@ -305,12 +325,44 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn,
  (void)instate; /* no use for this yet */

  if(smtpcode/100 != 2) {
    if(data->set.ftp_ssl > CURLUSESSL_TRY && !conn->ssl[FIRSTSOCKET].use)
      result = smtp_state_helo(conn);
    else {
      failf(data, "Access denied: %d", smtpcode);
      result = CURLE_LOGIN_DENIED;
    }
  } 
  else if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) {
    /* We don't have a SSL/TLS connection yet, but SSL is requested. Switch
       to TLS connection now */
    result = Curl_pp_sendf(&conn->proto.smtpc.pp, "STARTTLS", NULL);
    state(conn, SMTP_STARTTLS);
  }
  else {
    /* end the connect phase */
    state(conn, SMTP_STOP);
  }
  return result;
}

/* for HELO responses */
static CURLcode smtp_state_helo_resp(struct connectdata *conn,
                                     int smtpcode,
                                     smtpstate instate)
{
  CURLcode result = CURLE_OK;
  struct SessionHandle *data = conn->data;

  (void)instate; /* no use for this yet */

  if(smtpcode/100 != 2) {
    failf(data, "Access denied: %d", smtpcode);
    result = CURLE_LOGIN_DENIED;
  } 
  else {
    /* end the connect phase */
    state(conn, SMTP_STOP);
  }
  return result;
}

@@ -478,13 +530,6 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
        return CURLE_FTP_WEIRD_SERVER_REPLY;
      }

      if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) {
        /* We don't have a SSL/TLS connection yet, but SSL is requested. Switch
           to TLS connection now */
        result = Curl_pp_sendf(&smtpc->pp, "STARTTLS", NULL);
        state(conn, SMTP_STARTTLS);
      }
      else
      result = smtp_state_ehlo(conn);
      if(result)
        return result;
@@ -494,6 +539,10 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
      result = smtp_state_ehlo_resp(conn, smtpcode, smtpc->state);
      break;

    case SMTP_HELO:
      result = smtp_state_helo_resp(conn, smtpcode, smtpc->state);
      break;

    case SMTP_MAIL:
      result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
      break;
@@ -597,6 +646,10 @@ static CURLcode smtp_connect(struct connectdata *conn,
  const char *path = conn->data->state.path;
  int len;

#ifdef HAVE_GETHOSTNAME
    char localhost[1024 + 1];
#endif

  *done = FALSE; /* default to not done yet */

  /* If there already is a protocol-specific struct allocated for this
@@ -660,8 +713,14 @@ static CURLcode smtp_connect(struct connectdata *conn,
  pp->endofresp = smtp_endofresp;
  pp->conn = conn;

  if(!*path)
  if(!*path) {
#ifdef HAVE_GETHOSTNAME
    if(!gethostname(localhost, sizeof localhost))
      path = localhost;
    else
#endif
    path = "localhost";
  }

  /* url decode the path and use it as domain with EHLO */
  smtpc->domain = curl_easy_unescape(conn->data, path, 0, &len);
+1 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ typedef enum {
  SMTP_SERVERGREET, /* waiting for the initial greeting immediately after
                       a connect */
  SMTP_EHLO,
  SMTP_HELO,
  SMTP_STARTTLS,
  SMTP_MAIL, /* MAIL FROM */
  SMTP_RCPT, /* RCPT TO */
+1 −0
Original line number Diff line number Diff line
@@ -7,3 +7,4 @@
564
802
803
804
Loading