diff --git a/lib/imap.c b/lib/imap.c index 845d7dd4c..7738e63e2 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -323,16 +323,14 @@ static char* imap_atom(const char* str) return newstr; } -/* Function that checks for an ending IMAP status code at the start of the - given string but also detects various capabilities from the CAPABILITY - response including the supported authentication mechanisms. */ +/* Function that checks whether the given string is a valid tagged, untagged + or continuation response which can be processed by the response handler. */ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, int *resp) { struct imap_conn *imapc = &conn->proto.imapc; const char *id = imapc->resptag; size_t id_len = strlen(id); - size_t wordlen; /* Do we have a tagged command response? */ if(len >= id_len + 1 && !memcmp(id, line, id_len) && line[id_len] == ' ') { @@ -355,77 +353,19 @@ static bool imap_endofresp(struct connectdata *conn, char *line, size_t len, /* Do we have an untagged command response */ if(len >= 2 && !memcmp("* ", line, 2)) { - /* Are we processing CAPABILITY command data? */ - if(imapc->state == IMAP_CAPABILITY) { - line += 2; - len -= 2; - - /* 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++; - - /* Does the server support the STARTTLS capability? */ - if(wordlen == 8 && !memcmp(line, "STARTTLS", 8)) - imapc->tls_supported = TRUE; - - /* Has the server explicitly disabled clear text authentication? */ - else if(wordlen == 13 && !memcmp(line, "LOGINDISABLED", 13)) - imapc->login_disabled = TRUE; - - /* Does the server support the SASL-IR capability? */ - else if(wordlen == 7 && !memcmp(line, "SASL-IR", 7)) - imapc->ir_supported = TRUE; - - /* Do we have a SASL based authentication mechanism? */ - else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) { - line += 5; - len -= 5; - wordlen -= 5; - - /* Test the word for a matching authentication mechanism */ - if(wordlen == 5 && !memcmp(line, "LOGIN", 5)) - imapc->authmechs |= SASL_MECH_LOGIN; - if(wordlen == 5 && !memcmp(line, "PLAIN", 5)) - imapc->authmechs |= SASL_MECH_PLAIN; - else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8)) - imapc->authmechs |= SASL_MECH_CRAM_MD5; - else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10)) - imapc->authmechs |= SASL_MECH_DIGEST_MD5; - else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6)) - imapc->authmechs |= SASL_MECH_GSSAPI; - else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8)) - imapc->authmechs |= SASL_MECH_EXTERNAL; - else if(wordlen == 4 && !memcmp(line, "NTLM", 4)) - imapc->authmechs |= SASL_MECH_NTLM; - } - - line += wordlen; - len -= wordlen; - } - - return FALSE; + switch(imapc->state) { + /* States which are interested in untagged responses */ + case IMAP_CAPABILITY: + case IMAP_FETCH: + *resp = '*'; + break; + + /* Ignore other untagged responses */ + default: + return FALSE; } - /* Are we processing FETCH command responses? */ - else if(imapc->state == IMAP_FETCH) { - *resp = '*'; - return TRUE; - } + return TRUE; } /* Do we have a continuation response? */ @@ -755,10 +695,71 @@ static CURLcode imap_state_capability_resp(struct connectdata *conn, CURLcode result = CURLE_OK; struct SessionHandle *data = conn->data; struct imap_conn *imapc = &conn->proto.imapc; + const char *line = data->state.buffer; + size_t wordlen; (void)instate; /* no use for this yet */ - if(imapcode != 'O') + /* Do we have a untagged response? */ + if(imapcode == '*') { + line += 2; + + /* Loop through the data line */ + for(;;) { + while(*line && + (*line == ' ' || *line == '\t' || + *line == '\r' || *line == '\n')) { + + line++; + } + + if(!*line) + break; + + /* Extract the word */ + for(wordlen = 0; line[wordlen] && line[wordlen] != ' ' && + line[wordlen] != '\t' && line[wordlen] != '\r' && + line[wordlen] != '\n';) + wordlen++; + + /* Does the server support the STARTTLS capability? */ + if(wordlen == 8 && !memcmp(line, "STARTTLS", 8)) + imapc->tls_supported = TRUE; + + /* Has the server explicitly disabled clear text authentication? */ + else if(wordlen == 13 && !memcmp(line, "LOGINDISABLED", 13)) + imapc->login_disabled = TRUE; + + /* Does the server support the SASL-IR capability? */ + else if(wordlen == 7 && !memcmp(line, "SASL-IR", 7)) + imapc->ir_supported = TRUE; + + /* Do we have a SASL based authentication mechanism? */ + else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) { + line += 5; + wordlen -= 5; + + /* Test the word for a matching authentication mechanism */ + if(wordlen == 5 && !memcmp(line, "LOGIN", 5)) + imapc->authmechs |= SASL_MECH_LOGIN; + if(wordlen == 5 && !memcmp(line, "PLAIN", 5)) + imapc->authmechs |= SASL_MECH_PLAIN; + else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8)) + imapc->authmechs |= SASL_MECH_CRAM_MD5; + else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10)) + imapc->authmechs |= SASL_MECH_DIGEST_MD5; + else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6)) + imapc->authmechs |= SASL_MECH_GSSAPI; + else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8)) + imapc->authmechs |= SASL_MECH_EXTERNAL; + else if(wordlen == 4 && !memcmp(line, "NTLM", 4)) + imapc->authmechs |= SASL_MECH_NTLM; + } + + line += wordlen; + } + } + else if(imapcode != 'O') result = imap_state_login(conn); else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) { /* We don't have a SSL/TLS connection yet, but SSL is requested */