Beispiel #1
0
 // if enabled, logs commands and replies
 private void logCmdAndResp(string direction, string line)
 {
     if (AppGlobals.logVerbose)
     {
         AppGlobals.logMessage("{0}:{1} {2}: {3}", this._clientIP, this._sessionID, direction, line);
     }
 }
Beispiel #2
0
 // dump the current settings
 private static void dumpSettings()
 {
     // base/network
     AppGlobals.writeConsole("Host name..................: {0}", AppGlobals.hostName);
     AppGlobals.writeConsole("listen IP..................: {0}", AppGlobals.listenAddress);
     AppGlobals.writeConsole("listen port................: {0}", AppGlobals.listenPort);
     AppGlobals.writeConsole("Receive timeout............: {0}", AppGlobals.receiveTimeout);
     // hardlimits
     AppGlobals.writeConsole("Max errors.................: {0}", AppGlobals.maxSmtpErr);
     AppGlobals.writeConsole("Max NOOP...................: {0}", AppGlobals.maxSmtpNoop);
     AppGlobals.writeConsole("Max VRFY/EXPN..............: {0}", AppGlobals.maxSmtpVrfy);
     AppGlobals.writeConsole("Max RCPT TO................: {0}", AppGlobals.maxSmtpRcpt);
     // sessions
     AppGlobals.writeConsole("Max messages per session...: {0}", AppGlobals.maxMessages);
     AppGlobals.writeConsole("Max parallel sessions......: {0}", AppGlobals.maxSessions);
     // messages
     AppGlobals.writeConsole("Store message data.........: {0}", AppGlobals.storeData);
     AppGlobals.writeConsole("Storage path...............: {0}", AppGlobals.storePath);
     AppGlobals.writeConsole("Max message size...........: {0}", AppGlobals.maxDataSize);
     // logs
     AppGlobals.writeConsole("Logfiles path..............: {0}", AppGlobals.logPath);
     AppGlobals.writeConsole("Verbose logging............: {0}", AppGlobals.logVerbose);
     // tarpitting
     AppGlobals.writeConsole("Initial banner delay.......: {0}", AppGlobals.bannerDelay);
     AppGlobals.writeConsole("Error delay................: {0}", AppGlobals.errorDelay);
     // filtering/rejecting
     AppGlobals.writeConsole("Do tempfail (4xx) on DATA..: {0}", AppGlobals.doTempFail);
     AppGlobals.writeConsole("Check for early talkers....: {0}", AppGlobals.earlyTalkers);
     // DNS filtering
     AppGlobals.writeConsole("DNS Whitelists.............: {0}", AppGlobals.whiteLists.Length);
     AppGlobals.writeConsole("DNS Blacklists.............: {0}", AppGlobals.blackLists.Length);
     // local domains/mailboxes
     AppGlobals.writeConsole("Local domains..............: {0}", AppGlobals.LocalDomains.Count);
     AppGlobals.writeConsole("Local mailboxes............: {0}", AppGlobals.LocalMailBoxes.Count);
 }
Beispiel #3
0
        // closes the socket, terminates the session
        private void closeSession()
        {
            if (null != this._client)
            {
                if (this._client.Connected)
                {
                    sleepDown(25);
                }
                try { this._client.Close(); this._client = null; }
                catch { }
                if (!string.IsNullOrEmpty(this._clientIP))
                {
                    AppGlobals.writeConsole("client {0} disconnected, sess={1}, ID={2}.", this._clientIP, this._sessCount, this._sessionID);
                }
            }
            this._initOk = false;
            long sesscount = AppGlobals.removeSession();

            resetSession();
        }
Beispiel #4
0
        private string _mailDom = null;                                 // domain part of a mail address
        #endregion

        #region "instance"
        // init
        public SMTPsession(TcpClient client)
        {
            try
            {
                this._sessCount = AppGlobals.addSession();
                this._sessionID = AppGlobals.sessionID();
                this._hostName  = AppGlobals.hostName;

                if (null != AppGlobals.LocalDomains)
                {
                    this._mailDomains = AppGlobals.LocalDomains;
                }
                if (null != AppGlobals.LocalMailBoxes)
                {
                    this._mailBoxes = AppGlobals.LocalMailBoxes;
                }

                this._client   = client;
                this._clientIP = this._client.Client.RemoteEndPoint.ToString();
                int i = this._clientIP.IndexOf(':');
                if (-1 != i)
                {
                    this._clientIP = this._clientIP.Substring(0, i);
                }
                this._client.ReceiveTimeout = AppGlobals.receiveTimeout;

                this._stream           = this._client.GetStream();
                this._reader           = new StreamReader(this._stream);
                this._writer           = new StreamWriter(this._stream);
                this._writer.NewLine   = "\r\n";
                this._writer.AutoFlush = true;

                AppGlobals.writeConsole("client {0} connected, sess={1}, ID={2}.", this._clientIP, this._sessCount, this._sessionID);
                this._initOk = true;
            }
            catch (Exception ex)
            {
                AppGlobals.writeConsole("SMTPsession::Exception: " + ex.Message);
                closeSession();
            }
        }
Beispiel #5
0
        // logs session infos to logfile (at each mail); if you want to change
        // the log record format, this is the place to do it, just change the
        // "cols.Add" to include the columns you want and there you'll go :-)
        private void logSession()
        {
            // check if already logged
            if (this._lastMsgID == this._msgCount)
            {
                return;
            }
            this._lastMsgID = this._msgCount;

            // check if we got some data
            if (string.IsNullOrEmpty(this._heloStr))
            {
                this._heloStr = "-no-helo-";
            }
            if (string.IsNullOrEmpty(this._mailFrom))
            {
                this._mailFrom = "-no-from-";
            }
            // if (0 == this._rcptTo.Count) return;

            // build the log array
            List <string> cols = new List <string>();

            // current date/time
            cols.Add(DateTime.UtcNow.ToString("u"));

            // start date, session ID, client IP, helo
            cols.Add(this._startDate.ToString("u"));
            cols.Add(this._sessionID.ToString());
            cols.Add(this._clientIP);
            cols.Add(this._heloStr);

            // mail from
            if (!string.IsNullOrEmpty(this._mailFrom))
            {
                cols.Add(this._mailFrom);
            }
            else
            {
                cols.Add("");
            }

            // rcpt to
            if (this._rcptTo.Count > 0)
            {
                cols.Add(this._rcptTo.Count.ToString());
                cols.Add(string.Join(",", this._rcptTo));
            }
            else
            {
                cols.Add("0");
                cols.Add("-no-rcpt-");
            }

            // message # and message file name (if any)
            cols.Add(this._msgCount.ToString());
            if (!string.IsNullOrEmpty(this._msgFile))
            {
                cols.Add(this._msgFile);
            }
            else
            {
                cols.Add("-no-file-");
            }

            // dns listing
            if (!string.IsNullOrEmpty(this._dnsListType))
            {
                cols.Add(this._dnsListType);
                cols.Add(this._dnsListName);
                cols.Add(this._dnsListValue);
            }
            else
            {
                cols.Add("-not-listed-");
                cols.Add("-none-");
                cols.Add("0.0.0.0");
            }

            // early talker
            if (this._earlyTalker)
            {
                cols.Add("1");
            }
            else
            {
                cols.Add("0");
            }

            // noop/vrfy/err
            cols.Add(this._noopCount.ToString());
            cols.Add(this._vrfyCount.ToString());
            cols.Add(this._errCount.ToString());

            // builds and logs the record
            //string logRec = string.Join("|", cols);
            //AppGlobals.logSession("{0}", logRec);

            // builds the log record format string
            StringBuilder logFmt = new StringBuilder("{0}");

            for (int i = 1; i < cols.Count; i++)
            {
                logFmt.Append("|{" + i + "}");
            }

            // log the record
            AppGlobals.logSession(logFmt.ToString(), cols.ToArray <string>());
        }
Beispiel #6
0
        // main entry point
        static int Main(string[] args)
        {
            // our internal stuff
            IPAddress listenAddr = IPAddress.Loopback;
            int       listenPort = 25;
            int       retCode    = 0;

            // load the config
            loadConfig();

            // tell we're starting up and, if verbose, dump config parameters
            AppGlobals.writeConsole("{0} {1} starting up (NET {2})", AppGlobals.appName, AppGlobals.appVersion, AppGlobals.appRuntime);
            if (AppGlobals.logVerbose)
            {
                dumpSettings();
            }

            // setup the listening IP:port
            listenAddr = AppGlobals.listenIP;
            listenPort = AppGlobals.listenPort;

            // try starting the listener
            try
            {
                listener = new TcpListener(listenAddr, listenPort);
                listener.Start();
            }
            catch (Exception ex)
            {
                AppGlobals.writeConsole("Listener::Error: " + ex.Message);
                return(1);
            }

            // tell we're ready to accept connections
            AppGlobals.writeConsole("Listening for connections on {0}:{1}", listenAddr, listenPort);

            // run until interrupted (Ctrl-C in our case)
            while (!timeToStop)
            {
                try
                {
                    // wait for an incoming connection, accept it and spawn a thread to handle it
                    SMTPsession handler = new SMTPsession(listener.AcceptTcpClient());
                    Thread      thread  = new System.Threading.Thread(new ThreadStart(handler.handleSession));
                    thread.Start();
                }
                catch (Exception ex)
                {
                    // we got an error
                    retCode = 2;
                    AppGlobals.writeConsole("Handler::Error: " + ex.Message);
                    timeToStop = true;
                }
            }

            // finalize
            if (null != listener)
            {
                try { listener.Stop(); }
                catch { }
            }
            return(retCode);
        }
Beispiel #7
0
        // loads/parses the config values
        static void loadConfig()
        {
            // listen address
            IPAddress listenIP      = IPAddress.Loopback;
            string    listenAddress = ConfigurationManager.AppSettings["ListenAddress"];

            if (String.IsNullOrEmpty(listenAddress))
            {
                listenAddress = "127.0.0.1";
            }
            if (false == IPAddress.TryParse(listenAddress, out listenIP))
            {
                listenAddress = "127.0.0.1";
                listenIP      = IPAddress.Loopback;
            }

            // listen port
            int listenPort = int.Parse(ConfigurationManager.AppSettings["ListenPort"]);

            if ((listenPort < 1) || (listenPort > 65535))
            {
                listenPort = 25;
            }

            // receive timeout
            int receiveTimeout = int.Parse(ConfigurationManager.AppSettings["ReceiveTimeOut"]);

            if (receiveTimeout < 0)
            {
                receiveTimeout = 0;
            }

            // hostname (for the banner)
            string hostName = ConfigurationManager.AppSettings["HostName"];

            if (string.IsNullOrEmpty(hostName))
            {
                hostName = System.Net.Dns.GetHostEntry("").HostName;
            }

            // true=emits a "tempfail" when receiving the DATA command
            bool doTempFail = bool.Parse(ConfigurationManager.AppSettings["DoTempFail"]);

            // true=stores the email envelope and data into files
            bool storeData = bool.Parse(ConfigurationManager.AppSettings["StoreData"]);

            // max size for a given email message
            long storeSize = long.Parse(ConfigurationManager.AppSettings["MaxDataSize"]);

            if (storeSize < 0)
            {
                storeSize = 0;
            }

            // max # of messages for a session
            int maxMsgs = int.Parse(ConfigurationManager.AppSettings["MaxMessages"]);

            if (maxMsgs < 1)
            {
                maxMsgs = 10;
            }

            // path for the email storage
            string storePath = ConfigurationManager.AppSettings["StorePath"];

            if (String.IsNullOrEmpty(storePath))
            {
                storePath = Path.GetTempPath();
            }
            if (!storePath.EndsWith("\\"))
            {
                storePath = storePath + "\\";
            }

            // max # of parallel sessions, further requests will be rejected
            long maxSessions = long.Parse(ConfigurationManager.AppSettings["MaxSessions"]);

            if (maxSessions < 1)
            {
                maxSessions = 16;
            }

            // path for the log file
            string logPath = ConfigurationManager.AppSettings["LogPath"];

            if (String.IsNullOrEmpty(logPath))
            {
                logPath = Path.GetTempPath();
            }
            if (!logPath.EndsWith("\\"))
            {
                logPath = logPath + "\\";
            }

            // verbose logging
            bool verboseLog = bool.Parse(ConfigurationManager.AppSettings["VerboseLogging"]);

            // early talker detection
            bool earlyTalk = bool.Parse(ConfigurationManager.AppSettings["DoEarlyTalk"]);

            // DNS whitelist providers, empty to not perform the check
            string whiteLists = ConfigurationManager.AppSettings["RWLproviders"];

            string[] RWL = null;
            if (!string.IsNullOrEmpty(whiteLists))
            {
                RWL = whiteLists.Split(',');
            }

            // DNS blacklist providers, empty to not perform the check
            string blackLists = ConfigurationManager.AppSettings["RBLproviders"];

            string[] RBL = null;
            if (!string.IsNullOrEmpty(blackLists))
            {
                RBL = blackLists.Split(',');
            }

            // hardlimits for errors, noop etc..
            int maxErrors = int.Parse(ConfigurationManager.AppSettings["MaxSmtpErrors"]);

            if (maxErrors < 1)
            {
                maxErrors = 5;
            }
            int maxNoop = int.Parse(ConfigurationManager.AppSettings["MaxSmtpNoop"]);

            if (maxNoop < 1)
            {
                maxNoop = 7;
            }
            int maxVrfy = int.Parse(ConfigurationManager.AppSettings["MaxSmtpVrfy"]);

            if (maxVrfy < 1)
            {
                maxVrfy = 10;
            }
            int maxRcpt = int.Parse(ConfigurationManager.AppSettings["MaxSmtpRcpt"]);

            if (maxRcpt < 1)
            {
                maxRcpt = 100;
            }

            // delays (tarpitting)
            int bannerDelay = int.Parse(ConfigurationManager.AppSettings["BannerDelay"]);

            if (bannerDelay < 0)
            {
                bannerDelay = 0;
            }
            int errorDelay = int.Parse(ConfigurationManager.AppSettings["ErrorDelay"]);

            if (errorDelay < 0)
            {
                errorDelay = 0;
            }

            // local domains and mailboxes
            List <string> domains   = new List <string>();
            List <string> mailboxes = new List <string>();
            string        fileName  = ConfigurationManager.AppSettings["LocalDomains"];

            if (!string.IsNullOrEmpty(fileName))
            {
                domains = AppGlobals.loadFile(fileName);
            }
            fileName = ConfigurationManager.AppSettings["LocalMailBoxes"];
            if (!string.IsNullOrEmpty(fileName))
            {
                mailboxes = AppGlobals.loadFile(fileName);
            }

            // set the global values
            AppGlobals.listenIP       = listenIP;
            AppGlobals.listenAddress  = listenAddress;
            AppGlobals.listenPort     = listenPort;
            AppGlobals.receiveTimeout = receiveTimeout;
            AppGlobals.hostName       = hostName.ToLower();
            AppGlobals.doTempFail     = doTempFail;
            AppGlobals.storeData      = storeData;
            AppGlobals.maxDataSize    = storeSize;
            AppGlobals.maxMessages    = maxMsgs;
            AppGlobals.storePath      = storePath;
            AppGlobals.maxSessions    = maxSessions;
            AppGlobals.logPath        = logPath;
            AppGlobals.logVerbose     = verboseLog;
            AppGlobals.earlyTalkers   = earlyTalk;
            AppGlobals.whiteLists     = RWL;
            AppGlobals.blackLists     = RBL;
            AppGlobals.maxSmtpErr     = maxErrors;
            AppGlobals.maxSmtpNoop    = maxNoop;
            AppGlobals.maxSmtpVrfy    = maxVrfy;
            AppGlobals.maxSmtpRcpt    = maxRcpt;
            AppGlobals.bannerDelay    = bannerDelay;
            AppGlobals.errorDelay     = errorDelay;
            AppGlobals.LocalDomains   = domains;
            AppGlobals.LocalMailBoxes = mailboxes;
        }