Skip to content

Commit

Permalink
Support SASL additional data challenges at login
Browse files Browse the repository at this point in the history
  • Loading branch information
simonrob committed Nov 13, 2024
1 parent 5d8a85d commit 1995d10
Showing 1 changed file with 20 additions and 9 deletions.
29 changes: 20 additions & 9 deletions emailproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2065,14 +2065,18 @@ def process_data(self, byte_data):

# if authentication succeeds (or fails), remove our proxy from the client and ignore all further communication
# don't use a regex here as the tag must match exactly; RFC 3501 specifies uppercase 'OK', so startswith is fine
if str_response.startswith('%s OK' % self.client_connection.authentication_tag):
Log.info(self.info_string(), '[ Successfully authenticated IMAP connection - releasing session ]')
self.client_connection.authenticated = True
self.client_connection.authentication_tag = None
elif str_response.startswith('%s NO' % self.client_connection.authentication_tag):
super().process_data(byte_data) # an error occurred - just send to the client and exit
self.close()
return
if self.client_connection.authentication_tag:
if str_response.startswith('%s OK' % self.client_connection.authentication_tag):
Log.info(self.info_string(), '[ Successfully authenticated IMAP connection - releasing session ]')
self.client_connection.authenticated = True
self.client_connection.authentication_tag = None
elif str_response.startswith('+'):
# a separate request for error details (SASL additional data challenge) - the client should send b'\r\n'
pass
elif str_response.startswith('%s NO' % self.client_connection.authentication_tag):
super().process_data(byte_data) # an error occurred - just send to the client and exit
self.close()
return

# intercept pre-auth CAPABILITY response to advertise only AUTH=PLAIN (+SASL-IR) and re-enable LOGIN if required
if IMAP_CAPABILITY_MATCHER.match(str_response):
Expand Down Expand Up @@ -2174,6 +2178,9 @@ def process_data(self, byte_data):
Log.info(self.info_string(), '[ Successfully authenticated POP connection - releasing session ]')
self.client_connection.authenticated = True
super().process_data(byte_data)
elif str_data.startswith('+'):
# a separate request for error details (SASL additional data challenge) - the client should send b'\r\n'
super().process_data(byte_data)
else:
super().process_data(byte_data) # an error occurred - just send to the client and exit
self.close()
Expand Down Expand Up @@ -2302,9 +2309,13 @@ def process_data(self, byte_data):
Log.info(self.info_string(), '[ Successfully authenticated SMTP connection - releasing session ]')
self.client_connection.authenticated = True
super().process_data(byte_data)
elif str_data.startswith('334'):
# a separate request for error details (SASL additional data challenge) - the client should send b'\r\n'
super().process_data(byte_data)
else:
super().process_data(byte_data) # an error occurred - just send to the client and exit
self.close()
if len(str_data) >= 4 and str_data[3] == ' ': # responses may be multiline - wait for last part
self.close()

else:
super().process_data(byte_data) # a server->client interaction we don't handle; ignore
Expand Down

0 comments on commit 1995d10

Please sign in to comment.