-
Notifications
You must be signed in to change notification settings - Fork 304
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HPCC-32678 Add support for TLS communication to Std.System.Email.SendEmail() #19128
HPCC-32678 Add support for TLS communication to Std.System.Email.SendEmail() #19128
Conversation
Jira Issue: https://hpccsystems.atlassian.net//browse/HPCC-32678 Jirabot Action Result: |
common/remote/rmtsmtp.cpp
Outdated
@@ -472,8 +472,10 @@ class CMailInfo | |||
unsigned port; | |||
StringAttr sender; | |||
Owned<ISocket> socket; | |||
Owned<ISecureSocket> secureSocket; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this used ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. That was part of the test change and If forgot to remove it.
char* buffPtr = inbuff; | ||
while (buffPtr < (inbuff + inlen)) | ||
{ | ||
if (strncmp(buffPtr, "250", 3) == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the "250" occur not at the beginning of buffPtr ?
And if in this block, could buffPtr go past inbuff + inlen ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that there will always be at least one 250 response that serves as an acknowledgement of the EHLO. In my tests, that line was "250-Nice to meet you." but the exact wording is not dictated.
Response codes will always be at the beginning of the buffer, and 250 responses should be first if there is no error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I modified the size of the outer while() to abort earlier to avoid some scans outside of the buffer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, approved.
da4f77d
to
8e45a02
Compare
Thanks, Mark! @ghalliday Squashed and ready for merging. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dcamper one issue that probably should be fixed, and a couple of questions.
@@ -505,6 +506,20 @@ class CMailInfo | |||
validator.validateValue(subject.get(), "email subject"); | |||
} | |||
|
|||
void convertToTLSSocket() | |||
{ | |||
secureSocketContext.setown(createSecureSocketContext(ClientSocket)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for this PR, but does this need the ability to provide a client certificate for mtls? If so this will need enhanced configuration support (from a secret).
common/remote/rmtsmtp.cpp
Outdated
|
||
#if defined(_USE_OPENSSL) | ||
bool useTLS = false; | ||
if (inlen > 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (inlen > 12), otherwise a very short response could access invalid memory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The while condition a couple of lines down guards against an invalid access. Aborting the loop earlier is slightly more efficient, though.
bool useTLS = false; | ||
if (inlen > 0) | ||
{ | ||
// Walk the buffer, looking for the STARTTLS option |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth commenting that 250 responses must come first. Given the comment my expectation was that this would keep skipping to the next line through the buffer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
250 codes should be the only non-error responses at this point, but the options that are returned can be in any order. So really, this is a line-by-line scan, aborting as soon as we can process '250 STARTTLS' or '250-STARTTLS'.
common/remote/rmtsmtp.cpp
Outdated
void getEhloAndOptions(StringBuffer & out) | ||
{ | ||
// Initial EHLO and gather reply, which should contain ESMTP options | ||
getEhlo(out); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to fall back to HELO if EHLO not supported? Can we ignore for any modern mail server?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ESMTP came out in 1995 (RFC 1869). All mail servers should support ESMTP by now. That said, a misconfiguration on the server side could prompt a fallback to the original protocol. I will add that.
@ghalliday I incorporated your feedback in this latest commit. It included a slight refactoring to make the flow more sensible. Please give it another look. |
Note additional change: After reviewiing the RFC I discovered that the option name (STARTTLS) should be tested case-insensitive. I made that change to the code as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dcamper looks good. One trivial change. Please squash.
// Log error as a warning | ||
StringBuffer msg; | ||
info.addToWarnings(e->errorMessage(msg).str()); | ||
EXCLOG(MCoperatorError, e, "WARNING"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MCoperatorWarning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I copied that from a catch() a little further down in the code. Do you have a better way of doing this?
a720b2d
to
2c48403
Compare
@ghalliday Squashed. Thanks! |
@dcamper one final thought. What is the best version to target? Could this possibly break existing code? |
Any change introduces a possibility for things to go wrong. The most likely failure here lies with an errant external mail server. The possibilities include:
The possibility of a introducing an outright "failure to communicate" is very small, I think. All of that said, we can certainly retarget to 9.8 or even master (9.10) in an abundance of caution. |
Final thought: If this PR is not safe for 9.6.x then I doubt it would be safe for 9.8.x, either. So the choices will be either 9.6.x or master. |
Merged to 9.8.x for the moment because most production systems are not yet upgraded to that version. So I agree with your assesment of risk, a problem will not have the same potential impact. |
Type of change:
Checklist:
Smoketest:
Testing:
Testing performed by using a local SMTP dev tool (https://github.com/rnwood/smtp4dev) and monitoring the ESMTP conversation with various configurations.