only allow authentication of one or more users if they're using a specific ip address

Use this forum if you have problems with a hMailServer script, such as hMailServer WebAdmin or code in an event handler.
Post Reply
carlatpg99
New user
New user
Posts: 16
Joined: 2022-08-16 20:53

only allow authentication of one or more users if they're using a specific ip address

Post by carlatpg99 » 2024-03-02 09:10

What I'd like to do is only allow authentication of one or more users if they're using a specific ip address for all email protocols: smtp, pop3, and impap. I plan to use eventhandler.vbs for this.

Here's what I already know how to do:

1. I know how to check the client ip address using regex. I do this under Sub OnClientConnect(oClient).
2. I can write to the event viewer log using EventLog.Write, although that writes to hmailserver_events.log instead of hmailserver_year-month-day.log
3. I can ban the ip address using the function that I already added AutoBan
4. I have already disabled smtp authentication on the ports I don't need it enabled: 25

Here's what I'd like to do:

1. Not allow usernames that do not contain @ in them. When that happens, ban their ip address automatically.
2. If a specific username with the domain (IE test@test.com) in it is passed, and their ip address is allowed because it matches the regex value I'm using, for the username, allow it. Otherwise ban the ip address automatically.
3. Not allow usernames that end with a specific domain, such as test2.com. So the username test@test2.com would not be allowed and the ip address would be banned.

So for point 2, I'd like to setup rules like the following:

For the username test@test.com, only ip addresses 192.168.0.10 is allowed authentication. If the ip address 192.168.0.11 tries to connect using the username test@test.com, even if the password is correct, it should automatically ban that ip address.

Thank you.

edit: I'm also wondering where the documentation is for all the variables that eventhandler.vbs uses, such as all the possible variables under oClient.* like oClient.IPAddress.

palinka
Senior user
Senior user
Posts: 4503
Joined: 2017-09-12 17:57

Re: only allow authentication of one or more users if they're using a specific ip address

Post by palinka » 2024-03-03 01:17

There's nothing you can do in eventhandlers.vbs to prevent authentication. However, you can ban based on the combination of username and IP. You would do this in Sub OnAcceptMessage.

How many username/IP combinations are we talking about here? Something like this might work:

Code: Select all

Sub OnAcceptMessage(oClient, oMessage)

	If oClient.Port <> 25 Then
		If oClient.Username = "test@test.com" And oClient.IPAddress = "192.168.0.10" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "user@test.com" And oClient.IPAddress = "192.168.0.12" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "fred@test.com" And oClient.IPAddress = "192.168.0.22" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		Else 
			Result.Value = 2
			Result.Message = "Your access to this mail system has been rejected due to the sending MTA's poor reputation. If you believe that this failure is in error, please contact the intended recipient via alternate means."
			'
			' Your autoban code here
			'
		End If
	End If

End Sub
The above would strictly limit the system to those combinations of username/IP except on port 25 because that's where incoming mail comes from. This only works on SMTP.

The documentation for the client object is here: https://www.hmailserver.com/documentati ... ect_client

palinka
Senior user
Senior user
Posts: 4503
Joined: 2017-09-12 17:57

Re: only allow authentication of one or more users if they're using a specific ip address

Post by palinka » 2024-03-03 01:22

I *think* you can use the same code in OnClientLogon to boot non-authorized username/IP combinations from IMAP and POP3.

Code: Select all

Sub OnClientLogon(oClient)

	If oClient.Port <> 25 Then
		If oClient.Username = "test@test.com" And oClient.IPAddress = "192.168.0.10" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "user@test.com" And oClient.IPAddress = "192.168.0.12" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "fred@test.com" And oClient.IPAddress = "192.168.0.22" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		Else 
			'
			' Your autoban code here
			'
		End If
	End If

End Sub

User avatar
mattg
Moderator
Moderator
Posts: 22444
Joined: 2007-06-14 05:12
Location: 'The Outback' Australia

Re: only allow authentication of one or more users if they're using a specific ip address

Post by mattg » 2024-03-03 05:06

I do something similar from OnClientConnect

I only allow POP and IMAP connections from within Australia
Just 'cause I link to a page and say little else doesn't mean I am not being nice.
https://www.hmailserver.com/documentation

palinka
Senior user
Senior user
Posts: 4503
Joined: 2017-09-12 17:57

Re: only allow authentication of one or more users if they're using a specific ip address

Post by palinka » 2024-03-03 09:22

palinka wrote:
2024-03-03 01:22
I *think* you can use the same code in OnClientLogon to boot non-authorized username/IP combinations from IMAP and POP3.

Code: Select all

Sub OnClientLogon(oClient)

	If oClient.Port <> 25 Then
		If oClient.Username = "test@test.com" And oClient.IPAddress = "192.168.0.10" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "user@test.com" And oClient.IPAddress = "192.168.0.12" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "fred@test.com" And oClient.IPAddress = "192.168.0.22" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		Else 
			'
			' Your autoban code here
			'
		End If
	End If

End Sub
Actually, I think having this in OnClientLogon should work for all protocols - SMTP, IMAP & POP, since they all have to log on for any task. I didn't think about that last night.

User avatar
RvdH
Senior user
Senior user
Posts: 3249
Joined: 2008-06-27 14:42
Location: The Netherlands

Re: only allow authentication of one or more users if they're using a specific ip address

Post by RvdH » 2024-03-03 13:54

palinka wrote:
2024-03-03 09:22
palinka wrote:
2024-03-03 01:22
I *think* you can use the same code in OnClientLogon to boot non-authorized username/IP combinations from IMAP and POP3.

Code: Select all

Sub OnClientLogon(oClient)

	If oClient.Port <> 25 Then
		If oClient.Username = "test@test.com" And oClient.IPAddress = "192.168.0.10" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "user@test.com" And oClient.IPAddress = "192.168.0.12" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "fred@test.com" And oClient.IPAddress = "192.168.0.22" Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		Else 
			'
			' Your autoban code here
			'
		End If
	End If

End Sub
Actually, I think having this in OnClientLogon should work for all protocols - SMTP, IMAP & POP, since they all have to log on for any task. I didn't think about that last night.
OnClientLogon only is available as mod or in 5.7

PS, add oClient.Authenticated, eg:

Code: Select all

Sub OnClientLogon(oClient)

	If oClient.Port <> 25 Then
		If oClient.Username = "test@test.com" And oClient.IPAddress = "192.168.0.10" And oClient.Authenticated Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "user@test.com" And oClient.IPAddress = "192.168.0.12" And oClient.Authenticated Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "fred@test.com" And oClient.IPAddress = "192.168.0.22" And oClient.Authenticated Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		Else 
			'
			' Your autoban code here
			'
		End If
	End If

End Sub
CIDR to RegEx: d-fault.nl/cidrtoregex
DNS Lookup: d-fault.nl/dnstools
DKIM Generator: d-fault.nl/dkimgenerator
DNSBL Lookup: d-fault.nl/dnsbllookup
GEOIP Lookup: d-fault.nl/geoiplookup

palinka
Senior user
Senior user
Posts: 4503
Joined: 2017-09-12 17:57

Re: only allow authentication of one or more users if they're using a specific ip address

Post by palinka » 2024-03-03 18:06

RvdH wrote:
2024-03-03 13:54
PS, add oClient.Authenticated, eg:
Image

carlatpg99
New user
New user
Posts: 16
Joined: 2022-08-16 20:53

Re: only allow authentication of one or more users if they're using a specific ip address

Post by carlatpg99 » 2024-03-07 06:35

OnClientLogon is not available in 5.6.9-B2607.

And the variable oClient.Username is not available under Sub OnClientConnect(oClient).

I tested the same code under Sub OnAcceptMessage, and that seems to work. But as mentioned, that is only for smtp. I need this also working for pop3 and imap.

How would I prevent any usernames that do not contain the @ symbol though from trying to connect? Even if the password sent over is wrong, I still want to run them through the autoban code that is there if the username they send over does not contain the @ symbol in it.

Where do I go about getting 5.7 of hmailserver releases so I can use Sub OnClientLogon(oClient)?

found it here: viewtopic.php?f=10&t=30193&start=480

Here's the regex function I'm using by the way:

Code: Select all

Function RegExMatch(strString,strPattern)
    Dim RegEx
    RegExMatch=False

    Set RegEx = New RegExp
    RegEx.IgnoreCase = True
    RegEx.Global=True
    RegEx.Pattern=strPattern
    
    If RegEx.Test(strString) Then RegExMatch=True
End Function
To use it:

Code: Select all

If RegExMatch("teststring99","^teststring[0-9]+$") Then
    WScript.Echo "match"
Else
    WScript.Echo "no match"
End If
edit: oh and does oClient.Authenticated mean it will only be for those who send the correct username and password over? What about those who send an invalid username and/or password?

palinka
Senior user
Senior user
Posts: 4503
Joined: 2017-09-12 17:57

Re: only allow authentication of one or more users if they're using a specific ip address

Post by palinka » 2024-03-07 08:01

carlatpg99 wrote:
2024-03-07 06:35
How would I prevent any usernames that do not contain the @ symbol though from trying to connect? Even if the password sent over is wrong, I still want to run them through the autoban code that is there if the username they send over does not contain the @ symbol in it.
You can't prevent anyone from connecting - except by firewall and that would require seeing the future - but you can kick them out if they don't meet your criteria.
edit: oh and does oClient.Authenticated mean it will only be for those who send the correct username and password over? What about those who send an invalid username and/or password?
Correct - if authenticated, then true. If invalid, then false.

The problem you created for yourself is that you want specific combinations of username/IP. Therefore if you want to use regex to test those combinations, then your pattern will have to be made up of those combinations. Of course, you'll also have to present a combined string to be tested. I would suggest something like this.

Code: Select all

Function RegExMatch(strString)
	Dim RegEx
	RegExMatch=False

	Set RegEx = New RegExp
	RegEx.IgnoreCase = True
	RegEx.Global=True
	RegEx.Pattern="^test@test.com-192.168.0.10$|^user@test.com-192.168.0.12$|^fred@test.com-192.168.0.22$"

	If RegEx.Test(strString) Then RegExMatch=True
End Function

Sub OnClientLogon
	Dim CombiStr : CombiStr = oClient.Username & "-" & oClient.IPAddress
	If oClient.Authenticated And RegExMatch(CombiStr) Then
		EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
	Else
		'
		' Your autoban code here
		'
	End If
End Sub
This is virtually the same as I posted before, but less verbose.

User avatar
SorenR
Senior user
Senior user
Posts: 6322
Joined: 2006-08-21 15:38
Location: Denmark

Re: only allow authentication of one or more users if they're using a specific ip address

Post by SorenR » 2024-03-07 14:09

carlatpg99 wrote:
2024-03-07 06:35
OnClientLogon is not available in 5.6.9-B2607.

...
...

How would I prevent any usernames that do not contain the @ symbol though from trying to connect? Even if the password sent over is wrong, I still want to run them through the autoban code that is there if the username they send over does not contain the @ symbol in it.
1) Here viewtopic.php?p=252325#p252325

2) Leave Settings -> Advanced -> "Default domain" blank

3) Regarding AutoBan ... Choose your battles with caution. Exceeding 1-2,000 banned IP address will compromise the performance of your server and most probes will only attempt logon 1-3 times per week. I don't use the system generated AutoBan, I script it in Eventhandlers.vbs which gives me more control. The longest Ban I do is 48 hours.

Once you get into beeing "attacked" on a daily basis you'll learn to differentiate "annoying", "bad" and "ugly". 90% of your "attacks" fall into the category "annoying". "ugly" only occur about 3 times per year. ;-)
SørenR.

Woke is Marxism advancing through Maoist cultural revolution.

carlatpg99
New user
New user
Posts: 16
Joined: 2022-08-16 20:53

Re: only allow authentication of one or more users if they're using a specific ip address

Post by carlatpg99 » 2024-03-09 05:32

I've found that with more then 2000 ip addresses banned, performance has been fine. Plus I'm thinking what will happen when they do get into an email account. It can be way more then just using your email server to send out spam. I also need to make sure that the api for abuseipdb is not called multiple times for the same ip address that should have already been banned.

Thanks for letting me know to not set a default domain as a way to require @ in usernames.

Thanks for the link on where to find the updated hmailserver.

How do I write to a log file with a date format like: hmailserver_2022-02-28.log?

Right now

Code: Select all

EventLog.Write("test")
writes to a file named hmailserver_events.log.

carlatpg99
New user
New user
Posts: 16
Joined: 2022-08-16 20:53

Re: only allow authentication of one or more users if they're using a specific ip address

Post by carlatpg99 » 2024-03-09 06:53

Ok, I found a way to rename hmailserver_events.log to include the date of the previous day using a batch file that is ran once a day.

User avatar
SorenR
Senior user
Senior user
Posts: 6322
Joined: 2006-08-21 15:38
Location: Denmark

Re: only allow authentication of one or more users if they're using a specific ip address

Post by SorenR » 2024-03-09 13:38

carlatpg99 wrote:
2024-03-09 06:53
Ok, I found a way to rename hmailserver_events.log to include the date of the previous day using a batch file that is ran once a day.
Well.... This is from my EventHandlers.vbs ;-)

Code: Select all


Option Explicit

'******************************************************************************************************************************
'********** Configuration                                                                                            **********
'******************************************************************************************************************************
'
'   COM authentication
'
Private Const ADMIN       = "administrator"
Private Const PASSW       = "#SECRET#"
'
'   Misc. settings
'
Private Const LOGDIR      = "C:\hMailServer\Logs"

'******************************************************************************************************************************
'********** Classes                                                                                                  **********
'******************************************************************************************************************************

Class LogWriter

    Private m_oApp, m_ThreadID, m_LogFile, m_LogType, m_LogDir, m_LogSessionID
    Private i, t, temp, Append, Unicode, CurrTime, Elapsed, MilliSecs
    Private strDay, strMonth, strTime, strLogFile, strLogDate

    Private Sub Class_Initialize()
        Set m_oApp = CreateObject("hMailServer.Application")
        Call m_oApp.Authenticate(ADMIN, PASSW)
        m_LogFile = "LogWriter"
        m_LogType = "M"
        m_LogDir = LOGDIR
        m_ThreadID = Right("    " & CStr(m_oApp.Status.ThreadID),   4)
        m_LogSessionID = Empty
        Append = 8
        Unicode = -1
    End Sub

    Private Sub Class_Terminate()
        '
        '   Termination code goes here.
        '
    End Sub

    Private Function Wait(sec)
        With CreateObject("WScript.Shell")
            .Run "powershell Start-Sleep -Milliseconds " & Int(sec * 1000), 0, True
        End With
    End Function

    Private Function GetTimeStamp
        CurrTime = Now()
        Elapsed = Timer()
        MilliSecs = Int((Elapsed - Int(Elapsed)) * 1000)
        GetTimeStamp = Right("0000" & Year(CurrTime),   4) & "-" & _
                       Right("00"   & Month(CurrTime),  2) & "-" & _
                       Right("00"   & Day(CurrTime),    2) & " " & _
                       Right("00"   & Hour(CurrTime),   2) & ":" & _
                       Right("00"   & Minute(CurrTime), 2) & ":" & _
                       Right("00"   & Second(CurrTime), 2) & "." & _
                       Right("00"   & MilliSecs,        3)
    End Function

    Private Function OpenFile(strPath)
        On Error Resume Next
        With CreateObject("Scripting.FileSystemObject")
            For i = 0 To 30
                Err.Clear
                Set OpenFile = .OpenTextFile(strPath, Append, True, Unicode)
                If (Err.number <> 70) Then Exit For
                Wait(1)
            Next
        End With
        If (Err.number = 70) Then
            EventLog.Write( "ERROR: VBScript Class LogWriter" )
            EventLog.Write( "File " & strPath & " is locked and timeout was exceeded." )
            Err.Clear
        ElseIf Err Then
            EventLog.Write( "ERROR: VBScript Class LogWriter : Function OpenFile" )
            EventLog.Write( "Error       : " & Err.number )
            EventLog.Write( "Error (hex) : 0x" & Hex(Err.number) )
            EventLog.Write( "Source      : " & Err.Source )
            EventLog.Write( "Description : " & Err.Description )
            Err.Clear
        End If
        On Error GoTo 0
    End Function

    Private Function GetLogType(strType)
        CurrTime = Now()
        GetLogType = Right("0000" & Year(CurrTime),4) & "-" & Right("00" & Month(CurrTime), 2)
        If strType = "D" Then GetLogType = GetLogType & "-" & Right("00" & Day(CurrTime), 2)
    End Function

    Public Property Let LogFile(strFile)
        m_LogFile = Trim(strFile)
    End Property

    Public Property Let LogDir(strDir)
        If (Right(strDir, 1) = "\") Then
            m_LogDir = Trim(Left(strDir, Len(strDir) - 1))
        Else
            m_LogDir = Trim(strDir)
        End If
    End Property

    Public Property Let LogType(strType)
        m_LogType = Trim(strType)
    End Property

    Public Property Let LogSessionId(iSessionId)
        m_LogSessionID = Right("    " & Cstr(iSessionId),   4)
    End Property

    Public Function Write(strText)
        strLogFile = m_LogDir & "\" & m_LogFile & "_" & GetLogType(m_LogType) & ".log"
        On Error Resume Next
        With OpenFile(strLogFile)
            If Err Then EventLog.Write( ".WriteLine(" & m_ThreadID & vbTab & vbTab & Chr(34) & GetTimeStamp & Chr(34) & vbTab & Chr(34) & Trim(strText) & Chr(34) & ")" )
            If (IsEmpty(m_LogSessionID)) Then
                .WriteLine(m_ThreadID & vbTab & vbTab & Chr(34) & GetTimeStamp & Chr(34) & vbTab & Chr(34) & Trim(strText) & Chr(34))
            Else
                .WriteLine(m_ThreadID & vbTab & m_LogSessionID & vbTab & Chr(34) & GetTimeStamp & Chr(34) & vbTab & Chr(34) & Trim(strText) & Chr(34))
            End If
            .Close
        End With
        On Error GoTo 0
    End Function

End Class

'******************************************************************************************************************************
'********** hMailServer Triggers                                                                                     **********
'******************************************************************************************************************************

Sub OnError(iSeverity, iCode, sSource, sDescription)

    Dim EventLogX : Set EventLogX = New LogWriter
    EventLogX.LogFile = "error"

'
'    EventLogX.LogType = "D"          ... DAILY logs
'    EventLogX.LogType = "M"          ... MONTHLY logs (default)
'
'    EventLogX.LogFile = "<filename>" ... <filename>-YYYY-MM.log or <filename>-YYYY-MM-DD.log
'

    EventLogX.Write( "" )
    EventLogX.Write( "iSeverity: " & iSeverity )
    EventLogX.Write( "iCode: " & iCode )
    EventLogX.Write( "sSource: " & sSource )
    EventLogX.Write( "sDescription: " & sDescription )

    Set EventLogX = Nothing

End Sub

SAMPLE file: "error_2024-01.log"

Code: Select all


1900		"2024-01-02 23:28:11.726"	""
1900		"2024-01-02 23:28:11.726"	"iSeverity: 3"
1900		"2024-01-02 23:28:11.726"	"iCode: 4403"
1900		"2024-01-02 23:28:11.726"	"sSource: PersistentMessage::LoadHeader"
1900		"2024-01-02 23:28:11.726"	"sDescription: Could not read the message header, since the file was not available. File: C:\hMailServer\Data\{D4F2939A-DE41-4606-B320-6ED9933F8AB1}.eml"

SørenR.

Woke is Marxism advancing through Maoist cultural revolution.

carlatpg99
New user
New user
Posts: 16
Joined: 2022-08-16 20:53

Re: only allow authentication of one or more users if they're using a specific ip address

Post by carlatpg99 » 2024-03-22 11:16

SorenR wrote:
2024-03-09 13:38
carlatpg99 wrote:
2024-03-09 06:53
Ok, I found a way to rename hmailserver_events.log to include the date of the previous day using a batch file that is ran once a day.
Well.... This is from my EventHandlers.vbs ;-)

Code: Select all


Option Explicit

'******************************************************************************************************************************
'********** Configuration                                                                                            **********
'******************************************************************************************************************************
'
'   COM authentication
'
Private Const ADMIN       = "administrator"
Private Const PASSW       = "#SECRET#"
'
'   Misc. settings
'
Private Const LOGDIR      = "C:\hMailServer\Logs"

'******************************************************************************************************************************
'********** Classes                                                                                                  **********
'******************************************************************************************************************************

Class LogWriter

    Private m_oApp, m_ThreadID, m_LogFile, m_LogType, m_LogDir, m_LogSessionID
    Private i, t, temp, Append, Unicode, CurrTime, Elapsed, MilliSecs
    Private strDay, strMonth, strTime, strLogFile, strLogDate

    Private Sub Class_Initialize()
        Set m_oApp = CreateObject("hMailServer.Application")
        Call m_oApp.Authenticate(ADMIN, PASSW)
        m_LogFile = "LogWriter"
        m_LogType = "M"
        m_LogDir = LOGDIR
        m_ThreadID = Right("    " & CStr(m_oApp.Status.ThreadID),   4)
        m_LogSessionID = Empty
        Append = 8
        Unicode = -1
    End Sub

    Private Sub Class_Terminate()
        '
        '   Termination code goes here.
        '
    End Sub

    Private Function Wait(sec)
        With CreateObject("WScript.Shell")
            .Run "powershell Start-Sleep -Milliseconds " & Int(sec * 1000), 0, True
        End With
    End Function

    Private Function GetTimeStamp
        CurrTime = Now()
        Elapsed = Timer()
        MilliSecs = Int((Elapsed - Int(Elapsed)) * 1000)
        GetTimeStamp = Right("0000" & Year(CurrTime),   4) & "-" & _
                       Right("00"   & Month(CurrTime),  2) & "-" & _
                       Right("00"   & Day(CurrTime),    2) & " " & _
                       Right("00"   & Hour(CurrTime),   2) & ":" & _
                       Right("00"   & Minute(CurrTime), 2) & ":" & _
                       Right("00"   & Second(CurrTime), 2) & "." & _
                       Right("00"   & MilliSecs,        3)
    End Function

    Private Function OpenFile(strPath)
        On Error Resume Next
        With CreateObject("Scripting.FileSystemObject")
            For i = 0 To 30
                Err.Clear
                Set OpenFile = .OpenTextFile(strPath, Append, True, Unicode)
                If (Err.number <> 70) Then Exit For
                Wait(1)
            Next
        End With
        If (Err.number = 70) Then
            EventLog.Write( "ERROR: VBScript Class LogWriter" )
            EventLog.Write( "File " & strPath & " is locked and timeout was exceeded." )
            Err.Clear
        ElseIf Err Then
            EventLog.Write( "ERROR: VBScript Class LogWriter : Function OpenFile" )
            EventLog.Write( "Error       : " & Err.number )
            EventLog.Write( "Error (hex) : 0x" & Hex(Err.number) )
            EventLog.Write( "Source      : " & Err.Source )
            EventLog.Write( "Description : " & Err.Description )
            Err.Clear
        End If
        On Error GoTo 0
    End Function

    Private Function GetLogType(strType)
        CurrTime = Now()
        GetLogType = Right("0000" & Year(CurrTime),4) & "-" & Right("00" & Month(CurrTime), 2)
        If strType = "D" Then GetLogType = GetLogType & "-" & Right("00" & Day(CurrTime), 2)
    End Function

    Public Property Let LogFile(strFile)
        m_LogFile = Trim(strFile)
    End Property

    Public Property Let LogDir(strDir)
        If (Right(strDir, 1) = "\") Then
            m_LogDir = Trim(Left(strDir, Len(strDir) - 1))
        Else
            m_LogDir = Trim(strDir)
        End If
    End Property

    Public Property Let LogType(strType)
        m_LogType = Trim(strType)
    End Property

    Public Property Let LogSessionId(iSessionId)
        m_LogSessionID = Right("    " & Cstr(iSessionId),   4)
    End Property

    Public Function Write(strText)
        strLogFile = m_LogDir & "\" & m_LogFile & "_" & GetLogType(m_LogType) & ".log"
        On Error Resume Next
        With OpenFile(strLogFile)
            If Err Then EventLog.Write( ".WriteLine(" & m_ThreadID & vbTab & vbTab & Chr(34) & GetTimeStamp & Chr(34) & vbTab & Chr(34) & Trim(strText) & Chr(34) & ")" )
            If (IsEmpty(m_LogSessionID)) Then
                .WriteLine(m_ThreadID & vbTab & vbTab & Chr(34) & GetTimeStamp & Chr(34) & vbTab & Chr(34) & Trim(strText) & Chr(34))
            Else
                .WriteLine(m_ThreadID & vbTab & m_LogSessionID & vbTab & Chr(34) & GetTimeStamp & Chr(34) & vbTab & Chr(34) & Trim(strText) & Chr(34))
            End If
            .Close
        End With
        On Error GoTo 0
    End Function

End Class

'******************************************************************************************************************************
'********** hMailServer Triggers                                                                                     **********
'******************************************************************************************************************************

Sub OnError(iSeverity, iCode, sSource, sDescription)

    Dim EventLogX : Set EventLogX = New LogWriter
    EventLogX.LogFile = "error"

'
'    EventLogX.LogType = "D"          ... DAILY logs
'    EventLogX.LogType = "M"          ... MONTHLY logs (default)
'
'    EventLogX.LogFile = "<filename>" ... <filename>-YYYY-MM.log or <filename>-YYYY-MM-DD.log
'

    EventLogX.Write( "" )
    EventLogX.Write( "iSeverity: " & iSeverity )
    EventLogX.Write( "iCode: " & iCode )
    EventLogX.Write( "sSource: " & sSource )
    EventLogX.Write( "sDescription: " & sDescription )

    Set EventLogX = Nothing

End Sub

SAMPLE file: "error_2024-01.log"

Code: Select all


1900		"2024-01-02 23:28:11.726"	""
1900		"2024-01-02 23:28:11.726"	"iSeverity: 3"
1900		"2024-01-02 23:28:11.726"	"iCode: 4403"
1900		"2024-01-02 23:28:11.726"	"sSource: PersistentMessage::LoadHeader"
1900		"2024-01-02 23:28:11.726"	"sDescription: Could not read the message header, since the file was not available. File: C:\hMailServer\Data\{D4F2939A-DE41-4606-B320-6ED9933F8AB1}.eml"

Thank you very much! I will simply rename the file at the end of each day using a scheduled task for the time being.

carlatpg99
New user
New user
Posts: 16
Joined: 2022-08-16 20:53

Re: only allow authentication of one or more users if they're using a specific ip address

Post by carlatpg99 » 2024-03-23 01:42

I'm getting this error:

Code: Select all

"ERROR"	6820	"2024-03-22 16:32:42.566"	"Script Error: Source: Microsoft VBScript runtime error - Error: 800A01A8 - Description: Object required: 'Result' - Line: 306 Column: 4 - Code: (null)"
Here is the example code I'm using:

Code: Select all

Sub OnClientLogon(oClient)

	If oClient.Port <> 25 Then
		If oClient.Username = "test@test.com" And oClient.IPAddress = "192.168.0.10" And oClient.Authenticated Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "user@test.com" And oClient.IPAddress = "192.168.0.12" And oClient.Authenticated Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "fred@test.com" And oClient.IPAddress = "192.168.0.22" And oClient.Authenticated Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		Else 
		        Result.Value = 1
			'
			' Your autoban code here
			'
		End If
	End If

End Sub
Does Sub OnClientLogon not support setting Result.Value?

carlatpg99
New user
New user
Posts: 16
Joined: 2022-08-16 20:53

Re: only allow authentication of one or more users if they're using a specific ip address

Post by carlatpg99 » 2024-03-23 02:13

I also noticed that the autoban code is ran, but hmailserver allows them to finish the connection first. Such as checking for any new email messages to download. How do I prevent them from doing whatever action they were trying to do after successfully authenticating?

palinka
Senior user
Senior user
Posts: 4503
Joined: 2017-09-12 17:57

Re: only allow authentication of one or more users if they're using a specific ip address

Post by palinka » 2024-03-23 08:56

carlatpg99 wrote:
2024-03-23 01:42
I'm getting this error:

Code: Select all

"ERROR"	6820	"2024-03-22 16:32:42.566"	"Script Error: Source: Microsoft VBScript runtime error - Error: 800A01A8 - Description: Object required: 'Result' - Line: 306 Column: 4 - Code: (null)"
Here is the example code I'm using:

Code: Select all

Sub OnClientLogon(oClient)

	If oClient.Port <> 25 Then
		If oClient.Username = "test@test.com" And oClient.IPAddress = "192.168.0.10" And oClient.Authenticated Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "user@test.com" And oClient.IPAddress = "192.168.0.12" And oClient.Authenticated Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		ElseIf oClient.Username = "fred@test.com" And oClient.IPAddress = "192.168.0.22" And oClient.Authenticated Then
			EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in"
		Else 
		        Result.Value = 1
			'
			' Your autoban code here
			'
		End If
	End If

End Sub
Does Sub OnClientLogon not support setting Result.Value?
I guess the result object is not part of OnClientLogon. Unfortunately, since its part of an "experimental" build, there's no documentation for it. You can just remove it.

https://www.hmailserver.com/documentati ... ce_scripts

palinka
Senior user
Senior user
Posts: 4503
Joined: 2017-09-12 17:57

Re: only allow authentication of one or more users if they're using a specific ip address

Post by palinka » 2024-03-23 09:03

carlatpg99 wrote:
2024-03-23 02:13
I also noticed that the autoban code is ran, but hmailserver allows them to finish the connection first. Such as checking for any new email messages to download. How do I prevent them from doing whatever action they were trying to do after successfully authenticating?
I forgot about that. Basically, all the action takes place after login attempts. I guess this is not going to work after all. :roll:

However, you can still ban everyone except your list of IPs in OnClientConnect. That event happens before logon.

User avatar
SorenR
Senior user
Senior user
Posts: 6322
Joined: 2006-08-21 15:38
Location: Denmark

Re: only allow authentication of one or more users if they're using a specific ip address

Post by SorenR » 2024-03-23 11:53

carlatpg99 wrote:
2024-03-23 02:13
I also noticed that the autoban code is ran, but hmailserver allows them to finish the connection first. Such as checking for any new email messages to download. How do I prevent them from doing whatever action they were trying to do after successfully authenticating?
Using Result.Value instructs hMailServer on action AFTER the trigger exits... I usually use "exit sub" after AutoBanning or setting the Result.Value to force the action.
SørenR.

Woke is Marxism advancing through Maoist cultural revolution.

User avatar
SorenR
Senior user
Senior user
Posts: 6322
Joined: 2006-08-21 15:38
Location: Denmark

Re: only allow authentication of one or more users if they're using a specific ip address

Post by SorenR » 2024-03-23 14:01

Sub OnClienttLogin ...

5.6.9 (RvdH)

POP3: Result.Value = 1 ; "-ERR Invalid user name or password. Please use full email address as user name."
IMAP: Result.Value = 1 ; "Invalid user name or password. Please use full email address as user name."
SMTP: Result.Value = 1 ; RestartAuthentication_();


5.7

POP3: Result.Value NOT supported!
IMAP: Result.Value NOT supported!
SMTP: Result.Value NOT supported!

This could potentially become a problem!
SørenR.

Woke is Marxism advancing through Maoist cultural revolution.

carlatpg99
New user
New user
Posts: 16
Joined: 2022-08-16 20:53

Re: only allow authentication of one or more users if they're using a specific ip address

Post by carlatpg99 » 2024-03-26 05:36

I already ban ip addresses in OnClientConnect, and that allows me to use Result.Value = 1. But at that point I can't tell what username they are trying to login as.

I am running 5.6.9 (RvdH), version 5.6.9-B2641.67.

Here is an example of the script I'm using:

Code: Select all

Sub OnClientLogon(oClient)

	If oClient.Port <> 25 Then
		If oClient.Username = "test@test.com" Then
			If RegExMatch(oClient.IPAddress,"^10\.10\.10\.21$") And oClient.Authenticated Then
				EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in")
			Else
				'call autoban function here
				EventLog.Write("IP Address: " & oClient.IPAddress & " blocked from: " & oClient.Username & ".")
				Result.Value = 1
			End If
		End If
	End If

End Sub
I still get this error:

Code: Select all

"ERROR"	6492	"2024-03-25 19:35:59.933"	"Script Error: Source: Microsoft VBScript runtime error - Error: 800A01A8 - Description: Object required: 'Result' - Line: 310 Column: 4 - Code: (null)"
So I don't think Result.Value is part of Sub OnClientLogon.

I tried adding exit sub instead of Result.Value = 1, but that still allowed the action to go through before the ip address ban takes effect:

Code: Select all

Sub OnClientLogon(oClient)

	If oClient.Port <> 25 Then
		If oClient.Username = "test@test.com" Then
			If RegExMatch(oClient.IPAddress,"^10\.10\.10\.21$") And oClient.Authenticated Then
				EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in")
			Else
				'call autoban function here
				EventLog.Write("IP Address: " & oClient.IPAddress & " blocked from: " & oClient.Username & ".")
				exit sub
			End If
		End If
	End If

End Sub

carlatpg99
New user
New user
Posts: 16
Joined: 2022-08-16 20:53

Re: only allow authentication of one or more users if they're using a specific ip address

Post by carlatpg99 » 2024-03-26 05:58

Oh, the version 5.6.9-B2641.67 is not using openssl 3.0.13, if that makes a difference. So it's the version in 5.6.9-B2641.67.7z from https://d-fault.nl/files/hMailServer-Builds.

User avatar
mattg
Moderator
Moderator
Posts: 22444
Joined: 2007-06-14 05:12
Location: 'The Outback' Australia

Re: only allow authentication of one or more users if they're using a specific ip address

Post by mattg » 2024-03-26 09:00

Using that build, and adding this to your eventhandlers.vbs will log good and bad login attempts to your event log, with password used, and details of where from...

Code: Select all

Sub OnClientValidatePassword(oAccount, sPassword)
	EventLog.Write("New login attempt!!!!: " & oAccount.Address & " with PW " & sPassword)
End Sub

Sub OnClientLogon(oClient)
	If oClient.Authenticated then
		EventLog.Write("Successful login for " & oClient.Username & " from " & oClient.IpAddress & " on port " & oClient.Port & "")
	Else
		EventLog.Write("Failed login for " & oClient.Username & " from " & oClient.IpAddress & " on port " & oClient.Port & "")
	End if
End Sub
Just 'cause I link to a page and say little else doesn't mean I am not being nice.
https://www.hmailserver.com/documentation

User avatar
RvdH
Senior user
Senior user
Posts: 3249
Joined: 2008-06-27 14:42
Location: The Netherlands

Re: only allow authentication of one or more users if they're using a specific ip address

Post by RvdH » 2024-03-26 09:23

mattg wrote:
2024-03-26 09:00
Using that build, and adding this to your eventhandlers.vbs will log good and bad login attempts to your event log, with password used, and details of where from...

Code: Select all

Sub OnClientValidatePassword(oAccount, sPassword)
	EventLog.Write("New login attempt!!!!: " & oAccount.Address & " with PW " & sPassword)
End Sub

Sub OnClientLogon(oClient)
	If oClient.Authenticated then
		EventLog.Write("Successful login for " & oClient.Username & " from " & oClient.IpAddress & " on port " & oClient.Port & "")
	Else
		EventLog.Write("Failed login for " & oClient.Username & " from " & oClient.IpAddress & " on port " & oClient.Port & "")
	End if
End Sub
5.6.x doesn't include OnClientValidatePassword
CIDR to RegEx: d-fault.nl/cidrtoregex
DNS Lookup: d-fault.nl/dnstools
DKIM Generator: d-fault.nl/dkimgenerator
DNSBL Lookup: d-fault.nl/dnsbllookup
GEOIP Lookup: d-fault.nl/geoiplookup

User avatar
SorenR
Senior user
Senior user
Posts: 6322
Joined: 2006-08-21 15:38
Location: Denmark

Re: only allow authentication of one or more users if they're using a specific ip address

Post by SorenR » 2024-03-26 09:41

carlatpg99 wrote:
2024-03-26 05:36
I tried adding exit sub instead of Result.Value = 1, but that still allowed the action to go through before the ip address ban takes effect:
You got it wrong... First set Result.Value =1 then exit sub..

Alternatively disconnect the ip session ... should be references in the forum how to.
SørenR.

Woke is Marxism advancing through Maoist cultural revolution.

User avatar
SorenR
Senior user
Senior user
Posts: 6322
Joined: 2006-08-21 15:38
Location: Denmark

Re: only allow authentication of one or more users if they're using a specific ip address

Post by SorenR » 2024-03-26 15:55

SorenR wrote:
2024-03-26 09:41
carlatpg99 wrote:
2024-03-26 05:36
I tried adding exit sub instead of Result.Value = 1, but that still allowed the action to go through before the ip address ban takes effect:
You got it wrong... First set Result.Value =1 then exit sub..

Alternatively disconnect the ip session ... should be references in the forum how to.

Code: Select all

Function Disconnect(strIP)
    Dim oExec
    With CreateObject("WScript.Shell")
        Set oExec = .Exec("cports /close * * " & strIP & " *")
        Rem Set oExec = .Exec("disconnect " & strIP)
        Rem Set oExec = .Exec("wkillcx " & strIP)
        While oExec.Status = 0
            .Run "powershell Start-Sleep -Milliseconds " & Int(1 * 1000), 0, True
        Wend
    End With
    If oExec.Status = 1 Then
        EventLog.Write( "Disconnect code: " & oExec.StdOut.ReadAll)
    Else
        EventLog.Write( "Disconnect errorcode: " & oExec.StdErr.ReadAll)
    End If
    Set oExec = Nothing
End Function
SørenR.

Woke is Marxism advancing through Maoist cultural revolution.

carlatpg99
New user
New user
Posts: 16
Joined: 2022-08-16 20:53

Re: only allow authentication of one or more users if they're using a specific ip address

Post by carlatpg99 » 2024-03-27 02:56

So I tried setting result.value = 1 and then exit sub, and still got that same error here:

Code: Select all

"ERROR"	8932	"2024-03-26 17:03:46.083"	"Script Error: Source: Microsoft VBScript runtime error - Error: 800A01A8 - Description: Object required: 'Result' - Line: 310 Column: 4 - Code: (null)"
Here is my example code:

Code: Select all

Sub OnClientLogon(oClient)

	If oClient.Port <> 25 Then
		If oClient.Username = "test@test.com" Then
			If RegExMatch(oClient.IPAddress,"^10\.10\.10\.21$") And oClient.Authenticated Then
				EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in")
			Else
				'call autoban function here
				EventLog.Write("IP Address: " & oClient.IPAddress & " blocked from: " & oClient.Username & ".")
				Result.Value = 1
				exit sub
			End If
		End If
	End If

End Sub
So I don't think Sub OnClientLogon supports setting Result.Value = 1 here.

I downloaded cports.exe from: https://www.nirsoft.net/utils/cports.html
And copied cports.exe to C:\windows\

Then I added the disconnect code:

Code: Select all

Function Disconnect(strIP)
    Dim oExec
    With CreateObject("WScript.Shell")
        Set oExec = .Exec("cports /close * * " & strIP & " *")
        Rem Set oExec = .Exec("disconnect " & strIP)
        Rem Set oExec = .Exec("wkillcx " & strIP)
        While oExec.Status = 0
            .Run "powershell Start-Sleep -Milliseconds " & Int(1 * 1000), 0, True
        Wend
    End With
    If oExec.Status = 1 Then
        EventLog.Write( "Disconnect code: " & oExec.StdOut.ReadAll)
    Else
        EventLog.Write( "Disconnect errorcode: " & oExec.StdErr.ReadAll)
    End If
    Set oExec = Nothing
End Function
And modified the example code:

Code: Select all

Sub OnClientLogon(oClient)

	If oClient.Port <> 25 Then
		If oClient.Username = "test@test.com" Then
			If RegExMatch(oClient.IPAddress,"^10\.10\.10\.21$") And oClient.Authenticated Then
				EventLog.Write(oClient.Username & " on IP " & oClient.IPAddress & " successfully logged in")
			Else
				'call autoban function here
				Call Disconnect(oClient.IPAddress)
				EventLog.Write("IP Address: " & oClient.IPAddress & " blocked from: " & oClient.Username & ".")
			End If
		End If
	End If

End Sub
And that seems to work. It bans the ip address and then disconnects their ip address preventing the action they were trying to attempt from happening.

If it's an email client, it will prompt them to enter in their email addresses password again.

Thank you very much!

One thing I noticed is that there is no exit code from the cports.exe process as the hmailserver_events.log has this only:

Code: Select all

"Disconnect code: "

User avatar
SorenR
Senior user
Senior user
Posts: 6322
Joined: 2006-08-21 15:38
Location: Denmark

Re: only allow authentication of one or more users if they're using a specific ip address

Post by SorenR » 2024-03-27 14:29

carlatpg99 wrote:
2024-03-27 02:56
So I tried setting result.value = 1 and then exit sub, and still got that same error here:

Code: Select all

"ERROR"	8932	"2024-03-26 17:03:46.083"	"Script Error: Source: Microsoft VBScript runtime error - Error: 800A01A8 - Description: Object required: 'Result' - Line: 310 Column: 4 - Code: (null)"
Exactly what version of hMailServer are you using?

If you are using 5.7 then YES, that version does not support "Result.Value" however 5.6.9-2641.67 should...
viewtopic.php?p=252325#p252325

And if that version does not do it then you can have mine... It's 95% similar to RvdH's 5.6.9, I've forked his version ;-)
SørenR.

Woke is Marxism advancing through Maoist cultural revolution.

Post Reply