Example #1
0
        /// <summary>
        /// Filters sender.
        /// </summary>
        /// <param name="from">Sender.</param>
        /// <param name="api">Reference to server API.</param>
        /// <param name="session">Reference to SMTP session.</param>
        /// <param name="errorText">Filtering error text what is returned to client. ASCII text, 100 chars maximum.</param>
        /// <returns>Returns true if sender is ok or false if rejected.</returns>
        public bool Filter(string from, IMailServerApi api, SMTP_Session session, out string errorText)
        {
            errorText = null;
            bool ok = false;

            // Don't check authenticated users or LAN IP
            if (session.IsAuthenticated || IsPrivateIP(session.RemoteEndPoint.Address))
            {
                return(true);
            }

            try
            {
                using (new TransactionScope(TransactionScopeOption.Suppress))
                {
                    var d = new NKDC(ApplicationConnectionString, null);
                    if (!(from o in d.ContactEmailsViews where o.Email == @from select o).Any())
                    {
                        errorText = "You must be a registered user to use the email support service.";
                        WriteFilterLog("Sender:" + from + " IP:" + session.RemoteEndPoint.Address.ToString() + " unregistered.\r\n");
                        return(false);
                    }
                    else
                    {
                        return(true);
                    }
                }
            }
            catch (Exception ex)
            {
                WriteFilterLog(string.Format("Sender:{0} IP:{1} caused exception.\r\nEX:{2}{3}\r\n__\r\n", from, session.RemoteEndPoint.Address, ex, ex.Message));
            }

            return(ok);
        }
        /// <summary>
        /// Filters sender.
        /// </summary>
        /// <param name="from">Sender.</param>
        /// <param name="api">Reference to server API.</param>
        /// <param name="session">Reference to SMTP session.</param>
        /// <param name="errorText">Filtering error text what is returned to client. ASCII text, 100 chars maximum.</param>
        /// <returns>Returns true if sender is ok or false if rejected.</returns>
        public bool Filter(string from,IMailServerApi api,SMTP_Session session,out string errorText)
        {
            errorText = "";
            string ip = session.RemoteEndPoint.Address.ToString();

            Dns_Client dns = new Dns_Client();

            bool ok = false;

            // Don't check PTR for authenticated session and LAN IP ranges
            if(session.Authenticated || ip.StartsWith("127.0.0.1") || ip.StartsWith("10.") || ip.StartsWith("192.168")){
                return true;
            }

            DnsServerResponse reponse = dns.Query(ip,QTYPE.PTR);
            if(reponse.ResponseCode == RCODE.NO_ERROR){
                foreach(PTR_Record rec in reponse.GetPTRRecords()){
                    if(rec.DomainName.ToLower() == session.EhloName.ToLower()){
                        ok = true;
                        break;
                    }
                }
            }

            if(!ok){
                errorText = "Bad EHLO/HELO name, you must have valid DNS PTR record for your EHLO name and IP.";
            }

            return ok;
        }
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="server">Server what owns this virtual server.</param>
 /// <param name="id">Virtual server ID.</param>
 /// <param name="name">Virtual server name.</param>
 /// <param name="apiInitString">Virtual server api initi string.</param>
 /// <param name="api">Virtual server API.</param>
 public VirtualServer(Server server,string id,string name,string apiInitString,IMailServerApi api)
 {
     m_pOwnerServer  = server;
     m_ID            = id;
     m_Name          = name;
     m_ApiInitString = apiInitString;
     m_pApi          = api;
 }
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="server"></param>
        /// <param name="api"></param>
        public FetchPop3(VirtualServer server,IMailServerApi api)
        {
            m_pServer   = server;
            m_pApi      = api;
            m_LastFetch = DateTime.Now.AddMinutes(-5);

            m_pTimer = new Timer();
            m_pTimer.Interval = 15000;
            m_pTimer.Elapsed += new ElapsedEventHandler(m_pTimer_Elapsed);
        }
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="api">Virtual server api</param>
        public RecycleBinManager(IMailServerApi api)
        {
            m_pApi          = api;

            m_pTimer = new Timer();
            m_pTimer.Interval = 1000 * 60 * 60;
            m_pTimer.Elapsed += new ElapsedEventHandler(m_pTimer_Elapsed);

            m_LastCleanTime = DateTime.MinValue;
        }
Example #6
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="server"></param>
        /// <param name="api"></param>
        public FetchPop3(VirtualServer server, IMailServerApi api)
        {
            m_pServer   = server;
            m_pApi      = api;
            m_LastFetch = DateTime.Now.AddMinutes(-5);

            m_pTimer          = new Timer();
            m_pTimer.Interval = 15000;
            m_pTimer.Elapsed += new ElapsedEventHandler(m_pTimer_Elapsed);
        }
Example #7
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="api">Virtual server api</param>
        public RecycleBinManager(IMailServerApi api)
        {
            m_pApi = api;

            m_pTimer          = new Timer();
            m_pTimer.Interval = 1000 * 60 * 60;
            m_pTimer.Elapsed += new ElapsedEventHandler(m_pTimer_Elapsed);
            m_pTimer.Enabled  = true;

            m_LastCleanTime = DateTime.MinValue;
        }
        /// <summary>
        /// Filters message.
        /// </summary>
        /// <param name="messageStream">Message stream which to filter.</param>
        /// <param name="filteredStream">Filtered stream.</param>
        /// <param name="sender">Senders email address.</param>
        /// <param name="recipients">Recipients email addresses.</param>
        /// <param name="api">Access to server API.</param>
        /// <param name="session">Reference to SMTP session.</param>
        /// <param name="errorText">Filtering error text what is returned to client. ASCII text, 500 chars maximum.</param>
        public FilterResult Filter(Stream messageStream,out Stream filteredStream,string sender,string[] recipients,IMailServerApi api,SMTP_Session session,out string errorText)
        {
            errorText = "";
            filteredStream = messageStream;

            try{
                messageStream.Position = 0;

            //		long pos = messageStream.Position;
                string headers = MimeUtils.ParseHeaders(messageStream).ToLower();
            //		messageStream.Position = pos;

                //--- Check required header fields ---------//
                bool headersOk = true;
                if(headers.IndexOf("from:") == -1){
                    errorText = "Required From: header field is missing !";
                    headersOk = false;
                }
                else if(headers.IndexOf("to:") == -1){
                    errorText = "Required To: header field is missing !";
                    headersOk = false;
                }
                else if(headers.IndexOf("subject:") == -1){
                    errorText = "Required Subject: header field is missing !";
                    headersOk = false;
                }
                //------------------------------------------//

                // Check invalid <CR> or <LF> in headers. Header may not contain <CR> without <LF>,
                // <CRLF> must be in pairs.
                if(headers.Replace("\r\n","").IndexOf("\r") > -1 || headers.Replace("\r\n","").IndexOf("\n") > -1){
                    errorText = "Message contains invalid  <CR> or <LF> combinations !";
                    headersOk = false;
                }
                //-------------------------------------------------------------------------------//

                if(!headersOk){
                    return FilterResult.Error;
                }
            }
            catch{
            }

            // Reset stream position
            messageStream.Position = 0;

            return FilterResult.Store;
        }
Example #9
0
        /// <summary>
		/// Filters sender.
		/// </summary>
		/// <param name="from">Sender.</param>
		/// <param name="api">Reference to server API.</param>
		/// <param name="session">Reference to SMTP session.</param>
		/// <param name="errorText">Filtering error text what is returned to client. ASCII text, 100 chars maximum.</param>
		/// <returns>Returns true if sender is ok or false if rejected.</returns>
        public bool Filter(string from, IMailServerApi api, SMTP_Session session, out string errorText)
        {
            errorText = null;
            bool ok = false;

            // Don't check authenticated users or LAN IP
            if (session.IsAuthenticated || IsPrivateIP(session.RemoteEndPoint.Address))
            {
                return true;
            }

            try
            {                
                using (new TransactionScope(TransactionScopeOption.Suppress))
                {
                    var d = new NKDC(ApplicationConnectionString, null);
                    if (!(from o in d.ContactEmailsViews where o.Email == @from select o).Any())
                    {
                        errorText = "You must be a registered user to use the email support service.";
                        WriteFilterLog("Sender:" + from + " IP:" + session.RemoteEndPoint.Address.ToString() + " unregistered.\r\n");
                        return false;
                    }
                    else
                    {
                        return true;
                    }
                }


            }
            catch (Exception ex)
            {
                WriteFilterLog(string.Format("Sender:{0} IP:{1} caused exception.\r\nEX:{2}{3}\r\n__\r\n", from, session.RemoteEndPoint.Address, ex, ex.Message));
            }

            return ok;
        }
Example #10
0
        /// <summary>
        /// Loads virtual server from xml file.
        /// </summary>
        internal void LoadVirtualServers()
        {
            try{
                if (!File.Exists(SCore.PathFix(m_StartupPath + "Settings\\localServers.xml")))
                {
                    return;
                }

                DateTime dateServers = File.GetLastWriteTime(SCore.PathFix(m_StartupPath + "Settings\\localServers.xml"));

                if (DateTime.Compare(dateServers, m_ServersFileDate) != 0)
                {
                    m_ServersFileDate = dateServers;

                    DataSet ds = new DataSet();
                    ds.Tables.Add("Servers");
                    ds.Tables["Servers"].Columns.Add("ID");
                    ds.Tables["Servers"].Columns.Add("Enabled");
                    ds.Tables["Servers"].Columns.Add("Name");
                    ds.Tables["Servers"].Columns.Add("API_assembly");
                    ds.Tables["Servers"].Columns.Add("API_class");
                    ds.Tables["Servers"].Columns.Add("API_initstring");
                    ds.ReadXml(SCore.PathFix(m_StartupPath + "Settings\\localServers.xml"));

                    if (ds.Tables.Contains("Servers"))
                    {
                        // Delete running virtual servers what has deleted.
                        for (int i = 0; i < m_pVirtualServers.Count; i++)
                        {
                            VirtualServer server = m_pVirtualServers[i];
                            bool          exists = false;
                            foreach (DataRow dr in ds.Tables["Servers"].Rows)
                            {
                                if (server.ID == dr["ID"].ToString())
                                {
                                    exists = true;
                                    break;
                                }
                            }
                            if (!exists)
                            {
                                server.Stop();
                                m_pVirtualServers.Remove(server);
                                i--;
                            }
                        }

                        // Add new added virtual servers what aren't running already.
                        foreach (DataRow dr in ds.Tables["Servers"].Rows)
                        {
                            //--- See if specified server already running, if so, skip it. --//
                            bool exists = false;
                            foreach (VirtualServer server in m_pVirtualServers)
                            {
                                if (server.ID == dr["ID"].ToString())
                                {
                                    exists         = true;
                                    server.Enabled = ConvertEx.ToBoolean(dr["Enabled"], true);
                                    break;
                                }
                            }
                            if (exists)
                            {
                                continue;
                            }
                            //--------------------------------------------------------------//

                            string id       = dr["ID"].ToString();
                            string name     = dr["Name"].ToString();
                            string assembly = dr["API_assembly"].ToString();
                            string apiClass = dr["API_class"].ToString();
                            string intiStr  = dr["API_initstring"].ToString();

                            IMailServerApi api           = LoadApi(assembly, apiClass, intiStr);
                            VirtualServer  virtualServer = new VirtualServer(this, id, name, intiStr, api);
                            m_pVirtualServers.Add(virtualServer);
                            virtualServer.Enabled = ConvertEx.ToBoolean(dr["Enabled"], true);
                        }
                    }
                }
            }
            catch (Exception x) {
                Error.DumpError(x, new System.Diagnostics.StackTrace());
            }
        }
        /// <summary>
        /// Restores specified message from recycle bin.
        /// </summary>
        /// <param name="messageID">Message ID which to restore.</param>
        /// <param name="api">Reference to API.</param>
        public static void RestoreFromRecycleBin(string messageID, IMailServerApi api)
        {
            using (FileStream fs = GetFile()){
                int delRowCount       = 0;
                StreamLineReader r    = new StreamLineReader(fs);
                long             pos  = fs.Position;
                string           line = r.ReadLineString();
                while (line != null)
                {
                    // Skip comment lines
                    if (!line.StartsWith("#"))
                    {
                        // Skip deleted row
                        if (line.StartsWith("\0"))
                        {
                            delRowCount++;
                        }
                        else
                        {
                            string[] row = TextUtils.SplitQuotedString(line, ' ');
                            // Delete row
                            if (row[0] == messageID)
                            {
                                string user   = row[2];
                                string folder = TextUtils.UnQuoteString(row[3]);

                                // Store message back to original user folder
                                using (FileStream stream = File.OpenRead(m_RecycleBinPath + messageID + ".eml")){
                                    // If folder doesn't exist, create it
                                    if (!api.FolderExists(user + "/" + folder))
                                    {
                                        api.CreateFolder("system", user, folder);
                                    }

                                    api.StoreMessage("system", user, folder, stream, DateTime.Now, new string[] { "Recent" });
                                }

                                // Delete row
                                byte[] linebytes = new byte[fs.Position - pos - 2];
                                fs.Position = pos;
                                fs.Write(linebytes, 0, linebytes.Length);
                                fs.Position += 2; // CRLF
                                delRowCount++;

                                // Delete recycle bin message
                                File.Delete(m_RecycleBinPath + messageID + ".eml");
                                break;
                            }
                        }
                    }

                    pos  = fs.Position;
                    line = r.ReadLineString();
                }

                // There are many deleted rows, vacuum(remove deleted rows) flags database.
                if (delRowCount > 500)
                {
                    Vacuum(fs);
                }
            }
        }
Example #12
0
        /// <summary>
        /// Restores specified message from recycle bin.
        /// </summary>
        /// <param name="messageID">Message ID which to restore.</param>
        /// <param name="api">Reference to API.</param>
        public static void RestoreFromRecycleBin(string messageID,IMailServerApi api)
        {
            using(FileStream fs = GetFile()){
                int              delRowCount = 0;
                StreamLineReader r           = new StreamLineReader(fs);
                long             pos         = fs.Position;
                string           line        = r.ReadLineString();
                while(line != null){
                    // Skip comment lines
                    if(!line.StartsWith("#")){
                        // Skip deleted row
                        if(line.StartsWith("\0")){
                            delRowCount++;
                        }
                        else{
                            string[] row = TextUtils.SplitQuotedString(line,' ');
                            // Delete row
                            if(row[0] == messageID){
                                string            user   = row[2];
                                string            folder = TextUtils.UnQuoteString(row[3]);

                                // Store message back to original user folder
                                using(FileStream stream = File.OpenRead(m_RecycleBinPath + messageID + ".eml")){
                                    // If folder doesn't exist, create it
                                    if(!api.FolderExists(user + "/" + folder)){
                                        api.CreateFolder("system",user,folder);
                                    }

                                    api.StoreMessage("system",user,folder,stream,DateTime.Now,new string[]{"Recent"});
                                }

                                // Delete row
                                byte[] linebytes = new byte[fs.Position - pos - 2];
                                fs.Position = pos;
                                fs.Write(linebytes,0,linebytes.Length);
                                fs.Position += 2; // CRLF
                                delRowCount++;

                                // Delete recycle bin message
                                File.Delete(m_RecycleBinPath + messageID + ".eml");
                                break;
                            }
                        }
                    }

                    pos  = fs.Position;
                    line = r.ReadLineString();
                }

                // There are many deleted rows, vacuum(remove deleted rows) flags database.
                if(delRowCount > 500){
                    Vacuum(fs);
                }
            }
        }
Example #13
0
        /// <summary>
		/// Filters sender.
		/// </summary>
		/// <param name="from">Sender.</param>
		/// <param name="api">Reference to server API.</param>
		/// <param name="session">Reference to SMTP session.</param>
		/// <param name="errorText">Filtering error text what is returned to client. ASCII text, 100 chars maximum.</param>
		/// <returns>Returns true if sender is ok or false if rejected.</returns>
		public bool Filter(string from,IMailServerApi api,SMTP_Session session,out string errorText)
		{	
			errorText = null;
			bool ok = true;

			// Don't check authenticated users or LAN IP
			if(session.IsAuthenticated || IsPrivateIP(session.RemoteEndPoint.Address)){
				return true;
			}
			
			try{
				//--- Load data -----------------------
				DataSet ds = new DataSet();				
                ds.Tables.Add("General");
                ds.Tables["General"].Columns.Add("CheckHelo");
                ds.Tables["General"].Columns.Add("LogRejections");
                ds.Tables.Add("BlackListSettings");
                ds.Tables["BlackListSettings"].Columns.Add("ErrorText");
                ds.Tables.Add("BlackList");
                ds.Tables["BlackList"].Columns.Add("IP");
                ds.Tables.Add("Servers");
                ds.Tables["Servers"].Columns.Add("Cost");
                ds.Tables["Servers"].Columns.Add("Server");
                ds.Tables["Servers"].Columns.Add("DefaultRejectionText");
				
				ds.ReadXml(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\lsDNSBL_Filter_db.xml");

                bool logRejections = false;

                #region General

                if(ds.Tables["General"].Rows.Count == 1){
                    if(Convert.ToBoolean(ds.Tables["General"].Rows[0]["CheckHelo"])){            
                        DnsServerResponse response = Dns_Client.Static.Query(session.EhloHost,DNS_QType.A);
                        // If dns server connection errors, don't block.
                        if(response.ConnectionOk && response.ResponseCode != DNS_RCode.SERVER_FAILURE){
                            bool found = false;
                            foreach(DNS_rr_A a in response.GetARecords()){
                                if(session.RemoteEndPoint.Address.Equals(a.IP)){
                                    found = true;

                                    break;
                                }
                            }
                            if(!found){
                                errorText = "Not valid DNS EHLO/HELO name for your IP '" + session.EhloHost + "' !";

                                return false;
                            }
                        }
                    }
                    logRejections = ConvertEx.ToBoolean(ds.Tables["General"].Rows[0]["LogRejections"]);
                }

                #endregion

                #region Balck List

                foreach(DataRow dr in ds.Tables["BlackList"].Rows){
                    if(IsAstericMatch(dr["IP"].ToString(),session.RemoteEndPoint.Address.ToString())){
                        errorText = ds.Tables["BlackListSettings"].Rows[0]["ErrorText"].ToString();

                        return false;
                    }
                }

                #endregion

                #region DNSBL
                                               
				foreach(DataRow dr in ds.Tables["Servers"].Rows){
                    DnsServerResponse dnsResponse =  Dns_Client.Static.Query(ReverseIP(session.RemoteEndPoint.Address) + "." + dr["Server"].ToString(),DNS_QType.ANY);                    
					DNS_rr_A[] recs = dnsResponse.GetARecords();
					if(recs.Length > 0){
					    if(logRejections){
						    WriteFilterLog("Sender:" + from + " IP:" + session.RemoteEndPoint.Address.ToString() + " blocked\r\n");
                        }

                        errorText = dr["DefaultRejectionText"].ToString();
                        // Server provided return text, use it
                        if(dnsResponse.GetTXTRecords().Length > 0){
                            errorText = dnsResponse.GetTXTRecords()[0].Text;
                        }
                        if(errorText == ""){
                            errorText = "You are in '" + dr["Server"].ToString() + "' rejection list !";
                        }

						return false;
					}
                }

                #endregion                
            }
			catch{
			}

			return ok;
        }
        /// <summary>
        /// Filters message.
        /// </summary>
        /// <param name="messageStream">Message stream which to filter.</param>
        /// <param name="filteredStream">Filtered stream.</param>
        /// <param name="sender">Senders email address.</param>
        /// <param name="recipients">Recipients email addresses.</param>
        /// <param name="api">Access to server API.</param>
        /// <param name="session">Reference to SMTP session.</param>
        /// <param name="errorText">Filtering error text what is returned to client. ASCII text, 500 chars maximum.</param>
        public FilterResult Filter(Stream messageStream,out Stream filteredStream,string sender,string[] recipients,IMailServerApi api,SMTP_Session session,out string errorText)
        {
            errorText = "";

            messageStream.Position = 0;
            filteredStream = messageStream; // we don't change message content, just return same stream

            try{
                //--- Load data -----------------------
                DataSet ds = new DataSet();
                DataTable dt = ds.Tables.Add("KewWords");
                dt.Columns.Add("Cost",typeof(int));
                dt.Columns.Add("KeyWord");

                dt = ds.Tables.Add("ContentMd5");
                dt.Columns.Add("Description");
                dt.Columns.Add("EntryMd5Value");
                ds.ReadXml(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\lsSpam_db.xml");

                //--- Do mime parts data md5 hash compare ----------------
                ArrayList entries = new ArrayList();
                Mime parser = Mime.Parse(messageStream);

                System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
                foreach(MimeEntity ent in parser.MimeEntities){
                    if(ent.Data != null){
                        string md5Hash = Convert.ToBase64String(md5.ComputeHash(ent.Data));

                        foreach(DataRow dr in ds.Tables["ContentMd5"].Rows){
                            // Message contains blocked content(attachment,...)
                            if(dr["EntryMd5Value"].ToString() == md5Hash){
                                WriteFilterLog(DateTime.Now.ToString() + " From:" + sender + " Subject:\"" + parser.MainEntity.Subject + "\"  Contained blocked content:hash=" + md5Hash + "\r\n");
                                return FilterResult.DontStore;
                            }
                        }
                    }
                }

                byte[] topLines = new byte[2000];
                if(messageStream.Length < 2000){
                    topLines = new byte[messageStream.Length];
                }
                messageStream.Read(topLines,0,topLines.Length);

                string lines = System.Text.Encoding.ASCII.GetString(topLines).ToLower();

                //--- Try spam keywords -----------
                int totalCost = 0;
                string keyWords = "";
                DataView dv = ds.Tables["KewWords"].DefaultView;
                dv.Sort = "Cost DESC";
                foreach(DataRowView drV in dv){
                    if(lines.IndexOf(drV.Row["KeyWord"].ToString().ToLower()) > -1){
                        totalCost += Convert.ToInt32(drV.Row["Cost"]);

                        keyWords += drV.Row["KeyWord"].ToString() + " cost:" + drV.Row["Cost"].ToString() + " ";

                        // Check that total cost isn't exceeded
                        if(totalCost > 99){
                            errorText = "Message was blocked by server and considered as SPAM !";

                            WriteFilterLog(DateTime.Now.ToString() + " From:" + sender + " Blocked KeyWords: " + keyWords + "\r\n");

                            return FilterResult.Error;
                        }
                    }
                }
                //---------------------------------

                // Reset stream position
                messageStream.Position = 0;

                return FilterResult.Store;
            }
            catch(Exception x){
                return FilterResult.DontStore;
            }
        }
Example #15
0
        /// <summary>
        /// Filters message.
        /// </summary>
        /// <param name="messageStream">Message stream which to filter.</param>
        /// <param name="filteredStream">Filtered stream.</param>
        /// <param name="sender">Senders email address.</param>
        /// <param name="recipients">Recipients email addresses.</param>
        /// <param name="api">Access to server API.</param>
        /// <param name="session">Reference to SMTP session.</param>
        /// <param name="errorText">Filtering error text what is returned to client. ASCII text, 500 chars maximum.</param>
        public FilterResult Filter(Stream messageStream, out Stream filteredStream, string sender, string[] recipients, IMailServerApi api, SMTP_Session session, out string errorText)
        {
            errorText      = null;
            filteredStream = null;

            try{
                // Store message to tmp file
                string file = API_Utlis.PathFix(Path.GetTempPath() + "\\" + Guid.NewGuid().ToString() + ".eml");
                using (FileStream fs = File.Create(file)){
                    byte[] data = new byte[messageStream.Length];
                    messageStream.Read(data, 0, data.Length);
                    fs.Write(data, 0, data.Length);
                }

                // Execute virus program to scan tmp message
                // #FileName - place holder is replaced with file
                DataSet ds = new DataSet();
                ds.Tables.Add("Settings");
                ds.Tables["Settings"].Columns.Add("Program");
                ds.Tables["Settings"].Columns.Add("Arguments");
                ds.Tables["Settings"].Columns.Add("VirusExitCode");
                ds.ReadXml(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\lsVirusFilter_db.xml");

                string virusSoft     = ds.Tables["Settings"].Rows[0]["Program"].ToString();
                string virusSoftArgs = ds.Tables["Settings"].Rows[0]["Arguments"].ToString().Replace("#FileName", file);
                int    virusExitCode = ConvertEx.ToInt32(ds.Tables["Settings"].Rows[0]["Program"], 1);

                int exitCode = 0;
                System.Diagnostics.ProcessStartInfo sInf = new System.Diagnostics.ProcessStartInfo(virusSoft, virusSoftArgs);
                sInf.CreateNoWindow  = true;
                sInf.UseShellExecute = false;
                System.Diagnostics.Process p = System.Diagnostics.Process.Start(sInf);
                if (p != null)
                {
                    p.WaitForExit(60000);
                    exitCode = p.ExitCode;
                }

                if (File.Exists(file))
                {
                    // Return scanned message and delete tmp file
                    using (FileStream fs = File.OpenRead(file)){
                        byte[] data = new byte[fs.Length];
                        fs.Read(data, 0, data.Length);

                        filteredStream = new MemoryStream(data);
                    }

                    File.Delete(file);
                }
                // Virus scanner deleted messaeg, probably contains virus
                else
                {
                    virusExitCode = exitCode;
                }

                // Do exit code mapping
                if (virusExitCode == exitCode)
                {
                    errorText = "Message is blocked, contains virus !";
                    return(FilterResult.Error);
                }
            }
            catch (Exception x) {
                string dummy = x.Message;
                // Virus scanning failed, allow message through
                filteredStream = messageStream;
            }

            return(FilterResult.Store);
        }
Example #16
0
        /// <summary>
		/// Filters message.
		/// </summary>
		/// <param name="messageStream">Message stream which to filter.</param>
		/// <param name="filteredStream">Filtered stream.</param>
		/// <param name="sender">Senders email address.</param>
		/// <param name="recipients">Recipients email addresses.</param>
		/// <param name="api">Access to server API.</param>
		/// <param name="session">Reference to SMTP session.</param>
		/// <param name="errorText">Filtering error text what is returned to client. ASCII text, 500 chars maximum.</param>
		public FilterResult Filter(Stream messageStream,out Stream filteredStream,string sender,string[] recipients,IMailServerApi api,SMTP_Session session,out string errorText)
		{
			errorText = null;
			filteredStream = null;
                        
			try{                
				// Store message to tmp file
				string file = API_Utlis.PathFix(Path.GetTempPath() + "\\" + Guid.NewGuid().ToString() + ".eml");
				using(FileStream fs = File.Create(file)){
                    byte[] data = new byte[messageStream.Length];
                    messageStream.Read(data,0,data.Length);
					fs.Write(data,0,data.Length);
				}

				// Execute virus program to scan tmp message
				// #FileName - place holder is replaced with file
				DataSet ds = new DataSet();
				ds.Tables.Add("Settings");
                ds.Tables["Settings"].Columns.Add("Program");
			    ds.Tables["Settings"].Columns.Add("Arguments");
                ds.Tables["Settings"].Columns.Add("VirusExitCode");
				ds.ReadXml(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\lsVirusFilter_db.xml");

				string virusSoft     = ds.Tables["Settings"].Rows[0]["Program"].ToString();
				string virusSoftArgs = ds.Tables["Settings"].Rows[0]["Arguments"].ToString().Replace("#FileName",file);
                int    virusExitCode = ConvertEx.ToInt32(ds.Tables["Settings"].Rows[0]["Program"],1);

                int exitCode = 0;
				System.Diagnostics.ProcessStartInfo sInf = new System.Diagnostics.ProcessStartInfo(virusSoft,virusSoftArgs);
				sInf.CreateNoWindow = true;
				sInf.UseShellExecute = false;
				System.Diagnostics.Process p = System.Diagnostics.Process.Start(sInf);
				if(p != null){
					p.WaitForExit(60000);
                    exitCode = p.ExitCode;
				}
                				
				if(File.Exists(file)){
					// Return scanned message and delete tmp file
					using(FileStream fs = File.OpenRead(file)){
						byte[] data = new byte[fs.Length];
						fs.Read(data,0,data.Length);

						filteredStream = new MemoryStream(data);
					}

					File.Delete(file);
				}
                // Virus scanner deleted messaeg, probably contains virus
                else{
                    virusExitCode = exitCode;
                }
				
                // Do exit code mapping
                if(virusExitCode == exitCode){
                    errorText = "Message is blocked, contains virus !";
					return FilterResult.Error;
                }
			}
			catch(Exception x){
                string dummy = x.Message;
                // Virus scanning failed, allow message through
                filteredStream = messageStream;                
			}
			
			return FilterResult.Store;
        }
Example #17
0
        /// <summary>
        /// Filters sender.
        /// </summary>
        /// <param name="from">Sender.</param>
        /// <param name="api">Reference to server API.</param>
        /// <param name="session">Reference to SMTP session.</param>
        /// <param name="errorText">Filtering error text what is returned to client. ASCII text, 100 chars maximum.</param>
        /// <returns>Returns true if sender is ok or false if rejected.</returns>
        public bool Filter(string from, IMailServerApi api, SMTP_Session session, out string errorText)
        {
            errorText = null;
            bool ok = true;

            // Don't check authenticated users or LAN IP
            if (session.IsAuthenticated || IsPrivateIP(session.RemoteEndPoint.Address))
            {
                return(true);
            }

            try{
                //--- Load data -----------------------
                DataSet ds = new DataSet();
                ds.Tables.Add("General");
                ds.Tables["General"].Columns.Add("CheckHelo");
                ds.Tables["General"].Columns.Add("LogRejections");
                ds.Tables.Add("BlackListSettings");
                ds.Tables["BlackListSettings"].Columns.Add("ErrorText");
                ds.Tables.Add("BlackList");
                ds.Tables["BlackList"].Columns.Add("IP");
                ds.Tables.Add("Servers");
                ds.Tables["Servers"].Columns.Add("Cost");
                ds.Tables["Servers"].Columns.Add("Server");
                ds.Tables["Servers"].Columns.Add("DefaultRejectionText");

                ds.ReadXml(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\lsDNSBL_Filter_db.xml");

                bool logRejections = false;

                #region General

                if (ds.Tables["General"].Rows.Count == 1)
                {
                    if (Convert.ToBoolean(ds.Tables["General"].Rows[0]["CheckHelo"]))
                    {
                        DnsServerResponse response = Dns_Client.Static.Query(session.EhloHost, DNS_QType.A);
                        // If dns server connection errors, don't block.
                        if (response.ConnectionOk && response.ResponseCode != DNS_RCode.SERVER_FAILURE)
                        {
                            bool found = false;
                            foreach (DNS_rr_A a in response.GetARecords())
                            {
                                if (session.RemoteEndPoint.Address.Equals(a.IP))
                                {
                                    found = true;

                                    break;
                                }
                            }
                            if (!found)
                            {
                                errorText = "Not valid DNS EHLO/HELO name for your IP '" + session.EhloHost + "' !";

                                return(false);
                            }
                        }
                    }
                    logRejections = ConvertEx.ToBoolean(ds.Tables["General"].Rows[0]["LogRejections"]);
                }

                #endregion

                #region Balck List

                foreach (DataRow dr in ds.Tables["BlackList"].Rows)
                {
                    if (IsAstericMatch(dr["IP"].ToString(), session.RemoteEndPoint.Address.ToString()))
                    {
                        errorText = ds.Tables["BlackListSettings"].Rows[0]["ErrorText"].ToString();

                        return(false);
                    }
                }

                #endregion

                #region DNSBL

                foreach (DataRow dr in ds.Tables["Servers"].Rows)
                {
                    DnsServerResponse dnsResponse = Dns_Client.Static.Query(ReverseIP(session.RemoteEndPoint.Address) + "." + dr["Server"].ToString(), DNS_QType.ANY);
                    DNS_rr_A[]        recs        = dnsResponse.GetARecords();
                    if (recs.Length > 0)
                    {
                        if (logRejections)
                        {
                            WriteFilterLog("Sender:" + from + " IP:" + session.RemoteEndPoint.Address.ToString() + " blocked\r\n");
                        }

                        errorText = dr["DefaultRejectionText"].ToString();
                        // Server provided return text, use it
                        if (dnsResponse.GetTXTRecords().Length > 0)
                        {
                            errorText = dnsResponse.GetTXTRecords()[0].Text;
                        }
                        if (errorText == "")
                        {
                            errorText = "You are in '" + dr["Server"].ToString() + "' rejection list !";
                        }

                        return(false);
                    }
                }

                #endregion
            }
            catch {
            }

            return(ok);
        }