From f70bfb8a7f2c72758be721b78a7e9f33321dca21 Mon Sep 17 00:00:00 2001 From: MegaBrutal Date: Fri, 12 Oct 2018 08:05:25 +0200 Subject: [PATCH] Listen on user-specified addresses Configuration key ListenPort has been changed to ListenAddress. Now it is possible to supply exact addresses to listen on instead of all addresses (0.0.0.0). Backward compatibility is kept, so old ListenPort values will still be interpreted (if no ListenAddress is present). ListenPort = 25 ==> ListenAddress = 0.0.0.0:25 Multiple listen addresses may be separated by commas, e.g. ListenAddress = 192.168.1.161:25,127.0.0.1:225 Port 25 is implied when no port is specified for an address. modified: Common.pas modified: Listener.pas modified: MgSMTP.pas modified: Network.pas --- Common.pas | 25 ++++++++++++++++++------- Listener.pas | 17 +++++++++-------- MgSMTP.pas | 6 +++--- Network.pas | 11 ++++++----- 4 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Common.pas b/Common.pas index 7692672..fadccc5 100644 --- a/Common.pas +++ b/Common.pas @@ -1,5 +1,5 @@ { - Copyright (C) 2010-2015 MegaBrutal + Copyright (C) 2010-2018 MegaBrutal This unit is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -73,10 +73,10 @@ type {FTimeCorrection: integer;} FTimeOffset: integer; FTimeOffsetStr: string; - FListenPorts: TStrings; + FListenAddresses: TStrings; public function GetVersionStr: string; - property ListenPorts: TStrings read FListenPorts; + property ListenAddresses: TStrings read FListenAddresses; property Databytes: longint read FDatabytes; {property TimeCorrection: integer read FTimeCorrection;} property TimeOffset: integer read FTimeOffset; @@ -465,14 +465,25 @@ begin end; constructor TMainServerConfig.Create(Config: TINIFile); +var i: integer; rawaddresslist: string; portlist: TStringList; begin inherited Create(Config.ReadString('Server', 'Name', ''), Config, 'Server'); - FListenPorts:= TStringList.Create; - FListenPorts.Delimiter:= ','; - FListenPorts.DelimitedText:= Config.ReadString('Server', 'ListenPort', '25'); + FListenAddresses:= TStringList.Create; + FListenAddresses.Delimiter:= ','; + + rawaddresslist:= Config.ReadString('Server', 'ListenAddress', ''); + if rawaddresslist <> '' then + FListenAddresses.DelimitedText:= rawaddresslist + else begin + portlist:= TStringList.Create; + portlist.Delimiter:= ','; + portlist.DelimitedText:= Config.ReadString('Server', 'ListenPort', '25'); + for i:= 0 to portlist.Count - 1 do + FListenAddresses.Add('0.0.0.0:' + portlist.Strings[i]); + portlist.Free; + end; FDatabytes:= Config.ReadInteger('Server', 'Databytes', 1024 * 1024 * 1024); - {FTimeCorrection:= Config.ReadInteger('Server', 'TimeCorrection', 0);} FTimeOffset:= Config.ReadInteger('Server', 'TimeOffset', Config.ReadInteger('Server', 'TimeCorrection', 0) * 100); FTimeOffsetStr:= MakeTimeOffsetStr(FTimeOffset); diff --git a/Listener.pas b/Listener.pas index b37662b..fc92edd 100644 --- a/Listener.pas +++ b/Listener.pas @@ -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,7 +38,7 @@ 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); @@ -57,11 +57,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,11 +128,11 @@ 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); + Logger.AddLine('Server', 'Listening on address: ' + Address + ':' + IntToStr(Port)); end; diff --git a/MgSMTP.pas b/MgSMTP.pas index 1cee119..2fbc6ce 100644 --- a/MgSMTP.pas +++ b/MgSMTP.pas @@ -1,6 +1,6 @@ { MegaBrutal's SMTP Server (MgSMTP) - Copyright (C) 2010-2016 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 @@ -49,7 +49,7 @@ const document what bugfix/feature are you testing with the actual build. This will be logged to help you differentiate outputs of subsequent builds in your logs. If left empty, it won't be added to the logs. } - DEVCOMMENT = 'Catch CTRL-C in user mode'; + DEVCOMMENT = 'ListenAddress'; var @@ -246,7 +246,7 @@ end; begin Out.writeln('MegaBrutal''s SMTP Server, version ' + VERSION_STR + ', ' + IntToStr(PLATFORM_BITS) + ' bits'); - Out.writeln('Copyright (C) 2010-2014 MegaBrutal'); + Out.writeln('Copyright (C) 2010-2018 MegaBrutal'); AddDevComment(Out); Out.writeln; diff --git a/Network.pas b/Network.pas index 5ef2616..10a95f9 100644 --- a/Network.pas +++ b/Network.pas @@ -1,6 +1,6 @@ { Basic object-oriented network functions - Copyright (C) 2010-2014 MegaBrutal + Copyright (C) 2010-2018 MegaBrutal This unit is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -99,10 +99,11 @@ type end; TTCPListener = class(TThread) - constructor Create(Port: word; FeatureRequest: word); + constructor Create(const Address: string; Port: word; FeatureRequest: word); {destructor Destroy; override;} private FFeatureRequest: word; + FListenAddress: string; FListenPort: word; FListenSocket: socket; sAddr: TSockAddr; @@ -163,8 +164,9 @@ begin end; -constructor TTCPListener.Create(Port: word; FeatureRequest: word); +constructor TTCPListener.Create(const Address: string; Port: word; FeatureRequest: word); begin + FListenAddress:= Address; FListenPort:= Port; FFeatureRequest:= FeatureRequest; FreeOnTerminate:= false; @@ -292,12 +294,11 @@ begin with sAddr do begin sin_family:= af_inet; sin_port:= htons(FListenPort); - sin_addr.s_addr:= 0; + sin_addr:= ResolveHost(FListenAddress); end; if fpBind(FListenSocket, @sAddr, sizeof(sAddr)) <> -1 then begin { It seems the maximum connection value isn't enforced by the Free Pascal library, so this 512 is a constant, dummy value. } - { TEMPORARY SETTING OF 1 FROM 512! } if fpListen(FListenSocket, 512) <> -1 then begin Result:= true; Start; -- 2.34.1