To boost the security of Sage X3 and prevent brute-force attacks, you might want to lock out a user after three unsuccessful login attempts. Here is how to do it, using workflow and a helper table:
First we will create the helper table. We do this in the GESATB function:
Fields tab:
Index tab:
This table will hold the number of unsuccessful login attempts for each user.
Next we need an action that will be triggered by the workflow. We create it in the GESACT function:
Do not forget to mark the Workflow checkbox!
Now we go to the Workflow rules function (GESAWA) and create the following workflow:
General tab:
Recipients tab:
Only one row. All fields should be empty or have the value of "No", except for Type and Recipients.
Action tab:
And the last thing we need to do is create the standard processing file for our ZPASS action. So we go to the editor (function ADOTRT) and create the ZPASSSTD file with this code:
Subprog PASS()
If GERR=6
If clalev([ZPS])=0 : Local File ZPASS [ZPS] : Endif
Read [ZPS]ZPS0=GUSER
If fstat=5
Raz [ZPS]
[F:ZPS]USER=GUSER
[F:ZPS]COUNT=1
Write [ZPS]
If fstat
Infbox("Error while writing [ZPS], fstat="+num$(fstat))
Endif
Elsif fstat
Infbox("Error while reading [ZPS], fstat="+num$(fstat))
Else
If [F:ZPS]COUNT>=3
If clalev([ZAUS])=0 : Local File AUTILIS [ZAUS] : Endif
Update [ZAUS] Where USR=GUSER With ENAFLG=1
Delete [ZPS] Where USER=GUSER
Else
[F:ZPS]COUNT+=1
Rewrite [ZPS]
If fstat
Infbox("Error while writing [ZPS], fstat="+num$(fstat))
Endif
Endif
Endif
Elsif GERR=0
If clalev([ZPS])=0 : Local File ZPASS [ZPS] : Endif
Delete [ZPS] Where USER=GUSER
Endif
End
And here is how it all works:
The workflow that we created is of type Miscellaneous and has the CON event code. This means that the workflow will be triggered on each connection to the application. The GERR global variable will be set to 6 if the provided connection password is incorrect (you might need to debug in order to see which is the right value of GERR - my Sage X3 documentation says that GERR is set to 1 when the password is incorrect, but in my case it turned out to be actually 6). The workflow runs the ZPASS action, which means that the code we placed in the ZPASSSTD file is executed. This code uses our ZPASS helper table to check if the user has three consecutive unsuccessful login attempts due to incorrect password, and if so, locks the user out by deactivating his record in the AUTILIS table (setting the ENAFLG field to 1).
Once locked out, the user cannot connect to X3 even with his correct password. An administrator will have to re-enable his record in the GESAUS function. And if the administrator locks himself out, he will have to change his record in the AUTILIS table (set the ENAFLG field to 2) directly in the database.