mirror of
https://github.com/moparisthebest/curl
synced 2024-12-22 08:08:50 -05:00
smtp: Moved EHLO response handling to smtp_state_ehlo_resp()
Similar to the processing of untagged CAPABILITY responses in IMAP moved the processing of multiline EHLO responses to smtp_state_ehlo_resp() and introduced an internal response code of one to differentiate a multiline continuation from the end of command. This also allows for the separate processing of multiline responses from commands such as VRFY and EXPN.
This commit is contained in:
parent
786cba1ada
commit
f16c0de4e9
172
lib/smtp.c
172
lib/smtp.c
@ -230,78 +230,27 @@ static bool smtp_endofresp(struct connectdata *conn, char *line, size_t len,
|
||||
{
|
||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||
bool result = FALSE;
|
||||
size_t wordlen;
|
||||
|
||||
/* Nothing for us */
|
||||
if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2]))
|
||||
return FALSE; /* Nothing for us */
|
||||
return FALSE;
|
||||
|
||||
/* Do we have a command response? This should be the response code followed
|
||||
by a space and optionally some text as per RFC-5321 and as outlined in
|
||||
Section 4. Examples of RFC-4954 but some e-mail servers ignore this and
|
||||
only send the response code instead. */
|
||||
result = (line[3] == ' ' || len == 5) ? TRUE : FALSE;
|
||||
if(result)
|
||||
only send the response code instead as per Section 4.2. */
|
||||
if(line[3] == ' ' || len == 5) {
|
||||
result = TRUE;
|
||||
*resp = curlx_sltosi(strtol(line, NULL, 10));
|
||||
|
||||
/* Are we processing EHLO command data? */
|
||||
if(smtpc->state == SMTP_EHLO && (!result || (result && *resp/100 == 2))) {
|
||||
line += 4;
|
||||
len -= 4;
|
||||
|
||||
/* Does the server support the STARTTLS capability? */
|
||||
if(len >= 8 && !memcmp(line, "STARTTLS", 8))
|
||||
smtpc->tls_supported = TRUE;
|
||||
|
||||
/* Does the server support the SIZE capability? */
|
||||
else if(len >= 4 && !memcmp(line, "SIZE", 4))
|
||||
smtpc->size_supported = TRUE;
|
||||
|
||||
/* Do we have the authentication mechanism list? */
|
||||
else if(len >= 5 && !memcmp(line, "AUTH ", 5)) {
|
||||
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))
|
||||
smtpc->authmechs |= SASL_MECH_LOGIN;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
|
||||
smtpc->authmechs |= SASL_MECH_PLAIN;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
|
||||
smtpc->authmechs |= SASL_MECH_CRAM_MD5;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
|
||||
smtpc->authmechs |= SASL_MECH_DIGEST_MD5;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
|
||||
smtpc->authmechs |= SASL_MECH_GSSAPI;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
|
||||
smtpc->authmechs |= SASL_MECH_EXTERNAL;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
|
||||
smtpc->authmechs |= SASL_MECH_NTLM;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
|
||||
smtpc->authmechs |= SASL_MECH_XOAUTH2;
|
||||
|
||||
line += wordlen;
|
||||
len -= wordlen;
|
||||
}
|
||||
}
|
||||
/* Make sure real server never sends internal value */
|
||||
if(*resp == 1)
|
||||
*resp = 0;
|
||||
}
|
||||
/* Do we have a multiline (continuation) response? */
|
||||
else if(line[3] == '-') {
|
||||
result = TRUE;
|
||||
*resp = 1; /* Internal response code */
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -774,10 +723,13 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
|
||||
CURLcode result = CURLE_OK;
|
||||
struct SessionHandle *data = conn->data;
|
||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||
const char *line = data->state.buffer;
|
||||
size_t len = strlen(line);
|
||||
size_t wordlen;
|
||||
|
||||
(void)instate; /* no use for this yet */
|
||||
|
||||
if(smtpcode/100 != 2) {
|
||||
if(smtpcode/100 != 2 && smtpcode != 1) {
|
||||
if((data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) &&
|
||||
!conn->bits.user_passwd)
|
||||
result = smtp_perform_helo(conn);
|
||||
@ -786,21 +738,83 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
|
||||
result = CURLE_REMOTE_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
|
||||
/* We don't have a SSL/TLS connection yet, but SSL is requested */
|
||||
if(smtpc->tls_supported)
|
||||
/* Switch to TLS connection now */
|
||||
result = smtp_perform_starttls(conn);
|
||||
else if(data->set.use_ssl == CURLUSESSL_TRY)
|
||||
/* Fallback and carry on with authentication */
|
||||
result = smtp_perform_authenticate(conn);
|
||||
else {
|
||||
failf(data, "STARTTLS not supported.");
|
||||
result = CURLE_USE_SSL_FAILED;
|
||||
else {
|
||||
line += 4;
|
||||
len -= 4;
|
||||
|
||||
/* Does the server support the STARTTLS capability? */
|
||||
if(len >= 8 && !memcmp(line, "STARTTLS", 8))
|
||||
smtpc->tls_supported = TRUE;
|
||||
|
||||
/* Does the server support the SIZE capability? */
|
||||
else if(len >= 4 && !memcmp(line, "SIZE", 4))
|
||||
smtpc->size_supported = TRUE;
|
||||
|
||||
/* Do we have the authentication mechanism list? */
|
||||
else if(len >= 5 && !memcmp(line, "AUTH ", 5)) {
|
||||
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))
|
||||
smtpc->authmechs |= SASL_MECH_LOGIN;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_PLAIN))
|
||||
smtpc->authmechs |= SASL_MECH_PLAIN;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_CRAM_MD5))
|
||||
smtpc->authmechs |= SASL_MECH_CRAM_MD5;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_DIGEST_MD5))
|
||||
smtpc->authmechs |= SASL_MECH_DIGEST_MD5;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_GSSAPI))
|
||||
smtpc->authmechs |= SASL_MECH_GSSAPI;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_EXTERNAL))
|
||||
smtpc->authmechs |= SASL_MECH_EXTERNAL;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_NTLM))
|
||||
smtpc->authmechs |= SASL_MECH_NTLM;
|
||||
else if(sasl_mech_equal(line, wordlen, SASL_MECH_STRING_XOAUTH2))
|
||||
smtpc->authmechs |= SASL_MECH_XOAUTH2;
|
||||
|
||||
line += wordlen;
|
||||
len -= wordlen;
|
||||
}
|
||||
}
|
||||
|
||||
if(smtpcode != 1) {
|
||||
if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
|
||||
/* We don't have a SSL/TLS connection yet, but SSL is requested */
|
||||
if(smtpc->tls_supported)
|
||||
/* Switch to TLS connection now */
|
||||
result = smtp_perform_starttls(conn);
|
||||
else if(data->set.use_ssl == CURLUSESSL_TRY)
|
||||
/* Fallback and carry on with authentication */
|
||||
result = smtp_perform_authenticate(conn);
|
||||
else {
|
||||
failf(data, "STARTTLS not supported.");
|
||||
result = CURLE_USE_SSL_FAILED;
|
||||
}
|
||||
}
|
||||
else
|
||||
result = smtp_perform_authenticate(conn);
|
||||
}
|
||||
}
|
||||
else
|
||||
result = smtp_perform_authenticate(conn);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -1344,7 +1358,7 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
|
||||
return result;
|
||||
|
||||
/* Store the latest response for later retrieval */
|
||||
if(smtpc->state != SMTP_QUIT)
|
||||
if(smtpc->state != SMTP_QUIT && smtpcode != 1)
|
||||
data->info.httpcode = smtpcode;
|
||||
|
||||
if(smtpcode) {
|
||||
|
Loading…
Reference in New Issue
Block a user