Commit 94d820b4 authored by Steve Holme's avatar Steve Holme
Browse files

pop3: Moved CAPA response handling to pop3_state_capa_resp()

Similar to the processing of untagged CAPABILITY responses in IMAP and
multi-line EHLO responses in SMTP, moved the processing of multi-line
CAPA responses to pop3_state_capa_resp().
parent 1cfb436a
Loading
Loading
Loading
Loading
+87 −82
Original line number Diff line number Diff line
@@ -236,7 +236,6 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
                           int *resp)
{
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  size_t wordlen;

  /* Do we have an error response? */
  if(len >= 4 && !memcmp("-ERR", line, 4)) {
@@ -248,77 +247,14 @@ static bool pop3_endofresp(struct connectdata *conn, char *line, size_t len,
  /* Are we processing CAPA command responses? */
  if(pop3c->state == POP3_CAPA) {
    /* Do we have the terminating line? */
    if(len >= 1 && !memcmp(line, ".", 1)) {
    if(len >= 1 && !memcmp(line, ".", 1))
      *resp = '+';
    else
      *resp = '*';

    return TRUE;
  }

    /* Does the server support the STLS capability? */
    if(len >= 4 && !memcmp(line, "STLS", 4))
      pop3c->tls_supported = TRUE;

    /* Does the server support clear text authentication? */
    else if(len >= 4 && !memcmp(line, "USER", 4))
      pop3c->authtypes |= POP3_TYPE_CLEARTEXT;

    /* Does the server support APOP authentication? */
    else if(len >= 4 && !memcmp(line, "APOP", 4))
      pop3c->authtypes |= POP3_TYPE_APOP;

    /* Does the server support SASL based authentication? */
    else if(len >= 5 && !memcmp(line, "SASL ", 5)) {
      pop3c->authtypes |= POP3_TYPE_SASL;

      /* Advance past the SASL keyword */
      line += 5;
      len -= 5;

      /* Loop through the data line */
      for(;;) {
        while(len &&
              (*line == ' ' || *line == '\t' ||
               *line == '\r' || *line == '\n')) {

          line++;
          len--;
        }

        if(!len)
          break;

        /* Extract the word */
        for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
              line[wordlen] != '\t' && line[wordlen] != '\r' &&
              line[wordlen] != '\n';)
          wordlen++;

        /* Test the word for a matching authentication mechanism */
        if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
          pop3c->authmechs |= SASL_MECH_LOGIN;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
          pop3c->authmechs |= SASL_MECH_PLAIN;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
          pop3c->authmechs |= SASL_MECH_CRAM_MD5;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
          pop3c->authmechs |= SASL_MECH_DIGEST_MD5;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
          pop3c->authmechs |= SASL_MECH_GSSAPI;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
          pop3c->authmechs |= SASL_MECH_EXTERNAL;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
          pop3c->authmechs |= SASL_MECH_NTLM;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
          pop3c->authmechs |= SASL_MECH_XOAUTH2;

        line += wordlen;
        len -= wordlen;
      }
    }

    return FALSE;
  }

  /* Do we have a command or continuation response? */
  if((len >= 3 && !memcmp("+OK", line, 3)) ||
     (len >= 1 && !memcmp("+", line, 1))) {
@@ -755,12 +691,78 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
  CURLcode result = CURLE_OK;
  struct SessionHandle *data = conn->data;
  struct pop3_conn *pop3c = &conn->proto.pop3c;
  const char *line = data->state.buffer;
  size_t len = strlen(line);
  size_t wordlen;

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

  if(pop3code != '+')
    result = pop3_perform_user(conn);
  else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
  /* Do we have a untagged response? */
  if(pop3code == '*') {
    /* Does the server support the STLS capability? */
    if(len >= 4 && !memcmp(line, "STLS", 4))
      pop3c->tls_supported = TRUE;

    /* Does the server support clear text authentication? */
    else if(len >= 4 && !memcmp(line, "USER", 4))
      pop3c->authtypes |= POP3_TYPE_CLEARTEXT;

    /* Does the server support APOP authentication? */
    else if(len >= 4 && !memcmp(line, "APOP", 4))
      pop3c->authtypes |= POP3_TYPE_APOP;

    /* Does the server support SASL based authentication? */
    else if(len >= 5 && !memcmp(line, "SASL ", 5)) {
      pop3c->authtypes |= POP3_TYPE_SASL;

      /* Advance past the SASL keyword */
      line += 5;
      len -= 5;

      /* Loop through the data line */
      for(;;) {
        while(len &&
              (*line == ' ' || *line == '\t' ||
               *line == '\r' || *line == '\n')) {

          line++;
          len--;
        }

        if(!len)
          break;

        /* Extract the word */
        for(wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
              line[wordlen] != '\t' && line[wordlen] != '\r' &&
              line[wordlen] != '\n';)
          wordlen++;

        /* Test the word for a matching authentication mechanism */
        if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_LOGIN))
          pop3c->authmechs |= SASL_MECH_LOGIN;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
          pop3c->authmechs |= SASL_MECH_PLAIN;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
          pop3c->authmechs |= SASL_MECH_CRAM_MD5;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
          pop3c->authmechs |= SASL_MECH_DIGEST_MD5;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
          pop3c->authmechs |= SASL_MECH_GSSAPI;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
          pop3c->authmechs |= SASL_MECH_EXTERNAL;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
          pop3c->authmechs |= SASL_MECH_NTLM;
        else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
          pop3c->authmechs |= SASL_MECH_XOAUTH2;

        line += wordlen;
        len -= wordlen;
      }
    }
  }
  else if(pop3code == '+') {
    if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
      /* We don't have a SSL/TLS connection yet, but SSL is requested */
      if(pop3c->tls_supported)
        /* Switch to TLS connection now */
@@ -775,6 +777,9 @@ static CURLcode pop3_state_capa_resp(struct connectdata *conn, int pop3code,
    }
    else
      result = pop3_perform_authentication(conn);
  }
  else
    result = pop3_perform_user(conn);

  return result;
}