mirror of
https://github.com/moparisthebest/curl
synced 2025-03-11 15:50:48 -04: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;
|
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
||||||
bool result = FALSE;
|
bool result = FALSE;
|
||||||
size_t wordlen;
|
|
||||||
|
|
||||||
|
/* Nothing for us */
|
||||||
if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2]))
|
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
|
/* 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
|
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
|
Section 4. Examples of RFC-4954 but some e-mail servers ignore this and
|
||||||
only send the response code instead. */
|
only send the response code instead as per Section 4.2. */
|
||||||
result = (line[3] == ' ' || len == 5) ? TRUE : FALSE;
|
if(line[3] == ' ' || len == 5) {
|
||||||
if(result)
|
result = TRUE;
|
||||||
*resp = curlx_sltosi(strtol(line, NULL, 10));
|
*resp = curlx_sltosi(strtol(line, NULL, 10));
|
||||||
|
|
||||||
/* Are we processing EHLO command data? */
|
/* Make sure real server never sends internal value */
|
||||||
if(smtpc->state == SMTP_EHLO && (!result || (result && *resp/100 == 2))) {
|
if(*resp == 1)
|
||||||
line += 4;
|
*resp = 0;
|
||||||
len -= 4;
|
}
|
||||||
|
/* Do we have a multiline (continuation) response? */
|
||||||
/* Does the server support the STARTTLS capability? */
|
else if(line[3] == '-') {
|
||||||
if(len >= 8 && !memcmp(line, "STARTTLS", 8))
|
result = TRUE;
|
||||||
smtpc->tls_supported = TRUE;
|
*resp = 1; /* Internal response code */
|
||||||
|
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -774,10 +723,13 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn, int smtpcode,
|
|||||||
CURLcode result = CURLE_OK;
|
CURLcode result = CURLE_OK;
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct smtp_conn *smtpc = &conn->proto.smtpc;
|
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 */
|
(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) &&
|
if((data->set.use_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) &&
|
||||||
!conn->bits.user_passwd)
|
!conn->bits.user_passwd)
|
||||||
result = smtp_perform_helo(conn);
|
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;
|
result = CURLE_REMOTE_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(data->set.use_ssl && !conn->ssl[FIRSTSOCKET].use) {
|
else {
|
||||||
/* We don't have a SSL/TLS connection yet, but SSL is requested */
|
line += 4;
|
||||||
if(smtpc->tls_supported)
|
len -= 4;
|
||||||
/* Switch to TLS connection now */
|
|
||||||
result = smtp_perform_starttls(conn);
|
/* Does the server support the STARTTLS capability? */
|
||||||
else if(data->set.use_ssl == CURLUSESSL_TRY)
|
if(len >= 8 && !memcmp(line, "STARTTLS", 8))
|
||||||
/* Fallback and carry on with authentication */
|
smtpc->tls_supported = TRUE;
|
||||||
result = smtp_perform_authenticate(conn);
|
|
||||||
else {
|
/* Does the server support the SIZE capability? */
|
||||||
failf(data, "STARTTLS not supported.");
|
else if(len >= 4 && !memcmp(line, "SIZE", 4))
|
||||||
result = CURLE_USE_SSL_FAILED;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1344,7 +1358,7 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
/* Store the latest response for later retrieval */
|
/* Store the latest response for later retrieval */
|
||||||
if(smtpc->state != SMTP_QUIT)
|
if(smtpc->state != SMTP_QUIT && smtpcode != 1)
|
||||||
data->info.httpcode = smtpcode;
|
data->info.httpcode = smtpcode;
|
||||||
|
|
||||||
if(smtpcode) {
|
if(smtpcode) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user