Skip to content

Commit

Permalink
Switch to smtplib.SMTP for more compliant SMTP handling
Browse files Browse the repository at this point in the history
The current "client" did not wait for the greeting to finish before
sending commands, and took some other liberties with the SMTP standard.
This causes issues with some servers.
  • Loading branch information
mxsasha committed Oct 8, 2024
1 parent 7c38a4e commit 2903e2b
Showing 1 changed file with 30 additions and 11 deletions.
41 changes: 30 additions & 11 deletions sslyze/connection_helpers/opportunistic_tls_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import struct
from abc import abstractmethod, ABC
from enum import Enum
from smtplib import SMTP, SMTPException
from typing import ClassVar, Optional


Expand Down Expand Up @@ -65,19 +66,37 @@ def __init__(self, smtp_ehlo_hostname: str):
self._smtp_ehlo_hostname = smtp_ehlo_hostname

def prepare_socket_for_tls_handshake(self, sock: socket.socket) -> None:
# Get the SMTP banner
sock.recv(2048)
# SMTP parsing has some complicated areas and some unusual but legal
# server behavior - this code uses Python's smtplib to handle the protocol.
smtp = SMTP(local_hostname=self._smtp_ehlo_hostname)
smtp.sock = sock

# Send a EHLO and wait for the 250 status
sock.send(f"EHLO {self._smtp_ehlo_hostname}\r\n".encode("ascii"))
data = sock.recv(2048)
if b"250 " not in data:
raise OpportunisticTlsError(f"SMTP EHLO was rejected: {repr(data)}")
try:
code, server_reply = smtp.getreply()
message = server_reply.decode()
except SMTPException as exc:
code, message = -1, str(exc)
if code != 220:
raise OpportunisticTlsError(f"Unable to find 220 service ready response: {message}")

try:
code, server_reply = smtp.getreply()
message = server_reply.decode()
except SMTPException as exc:
code, message = -1, str(exc)
if code != 250:
raise OpportunisticTlsError(f"SMTP EHLO was rejected: {message}")

if not smtp.has_extn("starttls"):
raise OpportunisticTlsError(f"Server does not support STARTTLS: {message}")

# Send a STARTTLS
sock.send(b"STARTTLS\r\n")
if b"220" not in sock.recv(2048):
raise OpportunisticTlsError("SMTP STARTTLS not supported")
try:
code, server_reply = smtp.getreply()
message = server_reply.decode()
except SMTPException as exc:
code, message = -1, str(exc)
if code != 220:
raise OpportunisticTlsError(f"SMTP STARTTLS rejected: {message}")


class _XmppHelper(_OpportunisticTlsHelper):
Expand Down

0 comments on commit 2903e2b

Please sign in to comment.