AUTH PLAIN

Use this forum if you have installed hMailServer and want to ask a question related to a production release of hMailServer. Before posting, please read the troubleshooting guide. A large part of all reported issues are already described in detail here.
Post Reply
mikedibella
Normal user
Normal user
Posts: 230
Joined: 2016-12-08 02:21

AUTH PLAIN

Post by mikedibella » 2020-09-17 20:47

I'm having trouble relaying to an MTA that is only offering AUTH PLAIN, but HMS is ignoring the capability response and still sends AUTH LOGIN. Any workaround?

mikedibella
Normal user
Normal user
Posts: 230
Joined: 2016-12-08 02:21

Re: AUTH PLAIN

Post by mikedibella » 2020-09-18 11:57

Well, for those interested, here's the relevant code.

Lines 323-382 of SMTPClientConnection.cpp defines the processing for machine state after HELO/ELHO is sent:

Code: Select all

   void
   SMTPClientConnection::ProtocolEHLOSent_(int code, const AnsiString &request)
   {
      if (!IsPositiveCompletion(code))
      {
         bool ehlo_required = GetConnectionSecurity() == CSSTARTTLSRequired ||
                              use_smtpauth_;

         if (ehlo_required)
         {
            // hMailServer is configured to require EHLO, but the remote server does not support it.
            UpdateAllRecipientsWithError_(500, "Server does not support EHLO command.", false);
            SendQUIT_();
         }
         else
         {
            // Server does not support EHLO, but we do not require it. Switch to HELO.
            String computer_name = Utilities::ComputerName(); 
            EnqueueWrite_("HELO " + computer_name);
            SetState_(HELOSENT);
         }

         return;
      }

      if (GetConnectionSecurity() == CSSTARTTLSRequired || 
          GetConnectionSecurity() == CSSTARTTLSOptional)
      {
         if (!IsSSLConnection())
         {
            if (request.Contains("STARTTLS"))
            {
               EnqueueWrite_("STARTTLS");
               SetState_(STARTTLSSENT);
               return;
            }
            else
            {
               // Remote server does not support STARTTLS
               if (GetConnectionSecurity() == CSSTARTTLSRequired)
               {
                  UpdateAllRecipientsWithError_(500, "Server does not support STARTTLS.", false);
                  SendQUIT_();
                  return;
               }
            }
         }
      }

      if (use_smtpauth_)
      {
         // Ask the server to initiate login process.
         EnqueueWrite_("AUTH LOGIN");
         SetState_(AUTHLOGINSENT);
      }
      else
      {
         ProtocolSendMailFrom_();
      }
   }
The only capability that is parsed from the HELO/ELHO response is whether or not STARTTLS is supported (line 353).

The current implementation attempts to negotiate STARTTLS if needed (line 353-357) after receiving the HELO/EHLO response, then sends AUTH LOGIN arbitrarily if authorization is needed (lines 372-377).

In the instant case, the affected MTA does not support any AUTH types until after STARTTLS is completed, so a second ELHO needs to be sent after STARTTLS to discover supported AUTH methods.

The current implementation would have to be reworked to trigger a second EHLO after STARTTLS, then parse the most recent ELHO response to discover the correct AUTH method, and process the appropriate authentication protocol (LOGIN or PLAIN) based on the what the server supports. CRAM-MD5 support could additionally be handled in this new code.

For systems supporting multiple types, a precedence of CRAM-MD5, followed by either LOGIN or PLAIN since they are both equal in security, could be processed.

Post Reply