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().
This commit is contained in:
Steve Holme 2013-12-20 07:12:12 +00:00
parent 1cfb436a2f
commit 94d820b4cb

@ -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,75 +247,12 @@ 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;
return TRUE;
}
/* Do we have a command or continuation response? */
@ -755,26 +691,95 @@ 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) {
/* We don't have a SSL/TLS connection yet, but SSL is requested */
if(pop3c->tls_supported)
/* Switch to TLS connection now */
result = pop3_perform_starttls(conn);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
result = pop3_perform_authentication(conn);
else {
failf(data, "STLS not supported.");
result = CURLE_USE_SSL_FAILED;
/* 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 */
result = pop3_perform_starttls(conn);
else if(data->set.use_ssl == CURLUSESSL_TRY)
/* Fallback and carry on with authentication */
result = pop3_perform_authentication(conn);
else {
failf(data, "STLS not supported.");
result = CURLE_USE_SSL_FAILED;
}
}
else
result = pop3_perform_authentication(conn);
}
else
result = pop3_perform_authentication(conn);
result = pop3_perform_user(conn);
return result;
}