Block more HTTP request methods
[mgsmtp.git] / Listener.pas
index a4d94f0516b36344c8ea6b80b89a235a5fdede93..fd607c95772ebd22eb51315e63521c47c98cd703 100644 (file)
@@ -1,6 +1,6 @@
 {
    MegaBrutal's SMTP Server (MgSMTP)
-   Copyright (C) 2010-2014 MegaBrutal
+   Copyright (C) 2010-2018 MegaBrutal
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
@@ -38,10 +38,12 @@ uses SysUtils, Classes, Base64, Network, NetRFC, RFCSMTP,
 type
 
    TMgSMTPListener = class(TTCPListener)
-      constructor Create(Port: word);
+      constructor Create(const Address: string; Port: word);
    protected
       procedure HandleClient(Connection: TTCPConnection); override;
       procedure ReceiveEMailData(TCP: TTCPRFCConnection; Response: TRFCReply; SpoolObject: TSpoolObjectCreator);
+   public
+      function StartListen: boolean;
    end;
 
 
@@ -57,11 +59,12 @@ var
 
 
 procedure StartListeners;
-var i: integer;
+var i: integer; address, port: string;
 begin
-   SetLength(MgSMTPListeners, MainServerConfig.ListenPorts.Count);
+   SetLength(MgSMTPListeners, MainServerConfig.ListenAddresses.Count);
    for i:= 0 to Length(MgSMTPListeners) - 1 do begin
-      MgSMTPListeners[i]:= TMgSMTPListener.Create(StrToIntDef(MainServerConfig.ListenPorts.Strings[i], STANDARD_SMTP_PORT));
+      SplitParameters(MainServerConfig.ListenAddresses.Strings[i], address, port, ':');
+      MgSMTPListeners[i]:= TMgSMTPListener.Create(address, StrToIntDef(port, STANDARD_SMTP_PORT));
       MgSMTPListeners[i].StartListen;
    end;
 end;
@@ -127,14 +130,22 @@ begin
 end;
 
 
-constructor TMgSMTPListener.Create(Port: word);
+constructor TMgSMTPListener.Create(const Address: string; Port: word);
 begin
    { Request connection objects with support for RFC-style commands & responses. }
-   inherited Create(Port, NET_TCP_RFCSUPPORT);
-   Logger.AddLine('Server', 'Listening on port: ' + IntToStr(Port));
+   inherited Create(Address, Port, NET_TCP_RFCSUPPORT);
 end;
 
 
+function TMgSMTPListener.StartListen: boolean;
+begin
+   Result:= inherited StartListen;
+   if Result then
+      Logger.AddLine('Server', 'Listening on address: ' + GetSockAddrStr)
+   else
+      Logger.AddLine('Server', 'Failed to listen on address: ' + GetSockAddrStr);
+end;
+
 procedure TMgSMTPListener.HandleClient(Connection: TTCPConnection);
 { This is the procedure that actually handles the clients. It receives
   an object that manages the established connection in the parameter.
@@ -219,7 +230,9 @@ begin
 
          if (Length(Cmd) = 0) or (not ReadSucceeded) or UnexpectedFail then { Nothing. }
 
-         else if (Cmd = 'GET') or (Cmd = 'HEAD') or (Cmd = 'POST') then begin
+         else if (Cmd = 'GET') or (Cmd = 'HEAD') or (Cmd = 'PUT') or (Cmd = 'POST')
+            or (Cmd = 'DELETE') or (Cmd = 'CONNECT') or (Cmd = 'OPTIONS')
+            or (Cmd = 'PATCH') or (Cmd = 'TRACE') then begin
             SendAndLogResponse(SMTP_R_SERVICE_NA, 'Please learn to speak SMTP for I won''t speak HTTP. Stop abusing my service!');
             UnexpectedFail:= true;
          end
@@ -507,8 +520,11 @@ begin
       Done:= false;
       repeat
          ReadOK:= TCP.ReadLn(Line);
-         if Line <> '.' then
-            SpoolObject.DeliverMessagePart(Line)
+         if Line <> '.' then begin
+            { If the line starts with a dot, remove it to comply with RFC. }
+            if (Length(Line) > 1) and (Line[1] = '.') then Delete(Line, 1, 1);
+            SpoolObject.DeliverMessagePart(Line);
+         end
          else
             Done:= true;
       until Done or (not ReadOK);