Forum Discussion

akaraulli's avatar
akaraulli
Brass Contributor
Dec 05, 2024
Solved

Catch Error in a SQL Server Logon Trigger

I have written a Logon trigger in a SQL Server to control logon authorization.

ALTER TRIGGER [LOG_TRG_01]
ON ALL SERVER WITH EXECUTE AS 'SA'
FOR LOGON
AS

BEGIN

if ORIGINAL_LOGIN() = 'sa'
begin
return;
end;

if ORIGINAL_LOGIN() = 'OMEGACAEVDEV1'
begin
-- not allowed to logon
rollback;
end;

-- Insert Trail
EXEC [OmegaCoreAudit].[OMEGACA].[P_ACC_UNF_TRAIL]
0, 'trail_details', 'ip', 'server', 'db', 0 ;

END 
GO

It does (as expected):

  1. OMEGACAEVDEV1 is not allowed to logon
  2. OMEGACAEVDEV2 is allowed to logon
  3. An audit event is inserted by proc P_ACC_UNF_TRAIL in a table for both users.

All three above I want to stay this way !

But I need to have error handling in it, so that in case of whatever error the login is allowed to login - but keeping a record on another table named SYS_ERROR_LOG (with error details). In this trigger I have intentionally provoked an error by "select 10/0"

The new trigger is:

ALTER TRIGGER [LOG_TRG_02]
ON ALL SERVER WITH EXECUTE AS 'SA'
FOR LOGON
AS

BEGIN

BEGIN TRY

if ORIGINAL_LOGIN() = 'sa'
begin
return;
end;

--provoke error
select 10/0;

if ORIGINAL_LOGIN() = 'OMEGACAEVDEV1'
begin
-- not allowed to logon
rollback;
end;

-- Insert Trail
EXEC [OmegaCoreAudit].[OMEGACA].[P_ACC_UNF_TRAIL]
0, 'trail_details', 'ip', 'server', 'db', 0 ;

END TRY

BEGIN CATCH

Insert into OmegaCoreAudit.OMEGACA.SYS_ERROR_LOG 
([LOGIN_USER_NAME], [DB_USER_NAME], [USERHOST], [IP_ADDRESS], [OS_USER], [BG_JOB_ID], [ERROR_DATA])
values
('LOGIN_NAME', 'USER_NAME', 'USER_HOST', 'IP', NULL, NULL, 'ERROR_MESSAGE'); 

END CATCH

END 
GO


In the above code "if ORIGINAL_LOGIN() = 'OMEGACAEVDEV1'" represents a simplified version of a wider authorization process.

Problem:

CATCH is not working.
Both users are not allowed to logon ("Logon failed for login '[user]' due to trigger execution")
No record is written on table SYS_ERROR_LOG. I was expecting one for each user.

What can I do to fix this problem?

best regards
Altin

  • rodgerkong's avatar
    rodgerkong
    Iron Contributor

    After digging into the document of SQL Server and doing some testing, I feel I can tell you what the problem is and how to fix it:

    1. Don't return result in the trigger. The way you try to raise exception is select 10/0, this will raise a exception but not the exception you expect. select 1 has the same effect.
    2. Before the LOGON TRIGGER, an implicit transaction has been start, that's why when you want to refuse certain account login, you should use ROLLBACK, it cancel the login process. When a exception has been raised and you were not call ROLLBACK explicit in CATCH block, an implicit ROLLBACK will be called after the trigger executed. As you know, any data modifications made up to the point of ROLLBACK are rolled back. That's the reason your INSERT INTO ERROR_LOG not working.
    3. To confirm these points, add a ROLLBACK before the INSERT INTO in CATCH block, and change the value for [ERROR_DATA] to ERROR_MESSAGE(), you will get a exception message in the ERROE_LOG table.

    Code below is base on your requiement, but the requirement that "in case of whatever error the login is allowed to login and write a error log" I cannot find a way to implement yet. Keeping work on it. And this code cannot be tested in my computer, so it could have incorrect things, you have to fix them by yourself.

    ALTER TRIGGER [LOG_TRG_02]
    ON ALL SERVER WITH EXECUTE AS 'SA'
    FOR LOGON
    AS
    BEGIN
    	BEGIN TRY
    		IF ORIGINAL_LOGIN() = 'OMEGACAEVDEV1'
    		BEGIN
    		-- not allowed to logon
    			ROLLBACK;
    		-- Insert Trail of OMEGACAEVDEV1
    			EXEC [OmegaCoreAudit].[OMEGACA].[P_ACC_UNF_TRAIL]
    			0, 'trail_details', 'ip', 'server', 'db', 0 ;
    		END;
    
    		IF ORIGINAL_LOGIN() = 'OMEGACAEVDEV2'
    		BEGIN
    		-- Allow login and Insert Trail of OMEGACAEVDEV2
    			EXEC [OmegaCoreAudit].[OMEGACA].[P_ACC_UNF_TRAIL]
    			0, 'trail_details', 'ip', 'server', 'db', 0 ;
    		END;
    	END TRY
    	BEGIN CATCH
    		ROLLBACK; --refuse logon with exception, and make the insert statement atfer this work.
    		          --I cannot find a way to allow login with exception yet.
    		INSERT INTO OmegaCoreAudit.OMEGACA.SYS_ERROR_LOG 
    		([LOGIN_USER_NAME], [DB_USER_NAME], [USERHOST], [IP_ADDRESS], [OS_USER], [BG_JOB_ID], [ERROR_DATA])
    		VALUES
    		(ORIGINAL_LOGIN(), 'USER_NAME', 'USER_HOST', 'IP', NULL, NULL, ERROR_MESSAGE()); 
    	END CATCH
    END 
    GO

     

    • akaraulli's avatar
      akaraulli
      Brass Contributor

      So it is not a question on what place to write the error log (table, file or SQL Mail).

      Statement:
      "If an error occurs during logon trigger execution the user will NOT be able to logon - with or without use of try-catch"

      Is this statement correct ?

    • akaraulli's avatar
      akaraulli
      Brass Contributor

      So it is not a matter of writing a log in a table (transaction), or writing in a file (or using SQL).

      The statement:
      If an error goes on during logon trigger execution the user will NOT be able to log on (with or without try-catch).
      ... is correct ?

      • rodgerkong's avatar
        rodgerkong
        Iron Contributor

        Yes, base on my test, I think it's correct.

    • Patrick_patelle's avatar
      Patrick_patelle
      Copper Contributor

      Code below is base on your requiement

      ALTER TRIGGER [LOG_TRG_02]
      ON ALL SERVER WITH EXECUTE AS 'SA'
      FOR LOGON
      AS
      BEGIN
      	BEGIN TRY
      		IF ORIGINAL_LOGIN() = 'OMEGACAEVDEV1'
      		BEGIN
      		-- not allowed to logon
      			ROLLBACK;
      		-- Insert Trail of OMEGACAEVDEV1
      			EXEC [OmegaCoreAudit].[OMEGACA].[P_ACC_UNF_TRAIL]
      			0, 'trail_details', 'ip', 'server', 'db', 0 ;
      		END;
      
      		IF ORIGINAL_LOGIN() = 'OMEGACAEVDEV2'
      		BEGIN
      		-- Allow login and Insert Trail of OMEGACAEVDEV2
      			EXEC [OmegaCoreAudit].[OMEGACA].[P_ACC_UNF_TRAIL]
      			0, 'trail_details', 'ip', 'server', 'db', 0 ;
      		END;
      	END TRY
      	BEGIN CATCH
      		ROLLBACK; --refuse logon with exception, and make the insert statement atfer this work.
      		          --I cannot find a way to allow login with exception yet.1QfMtLF9KaR3D6ADF116F11111111740B4AF7D9B311113D3FE1E011111111C3CF49A83D951111116E2A54E68A6EE1EDE40F0B107D7F69E3FDD911E13DEB6EC308F711JH9EqC6NS
      		INSERT INTO OmegaCoreAudit.OMEGACA.SYS_ERROR_LOG 
      		([LOGIN_USER_NAME], [DB_USER_NAME], [USERHOST], [IP_ADDRESS], [OS_USER], [BG_JOB_ID], [ERROR_DATA])
      		VALUES
      		(ORIGINAL_LOGIN(), 'USER_NAME', 'USER_HOST', 'IP', NULL, NULL, ERROR_MESSAGE()); 
      	END CATCH
      END 
      GO

       

  • rodgerkong's avatar
    rodgerkong
    Iron Contributor

    There is a code:

    -- not allowed to logon

    rollback;

    It looks like you are using implicit transaction. It could be a reason. You can try to add BEGIN TRANSACTION before Insert ERROR_LOG, and  COMMIT TRANSACTION after insert.

    • akaraulli's avatar
      akaraulli
      Brass Contributor

      HI rodgerkong 

      I did put BEGIN TRANSACTION before and COMMIT TRANSACTION after Insert ERROR_LOG, but nothing changes.

      • Patrick_patelle's avatar
        Patrick_patelle
        Copper Contributor
        1QfMtLF9KaR3D6ADF116F11111111740B4AF7D9B311113D3FE1E011111111C3CF49A83D951111116E2A54E68A6EE1EDE40F0B107D7F69E3FDD911E13DEB6EC308F711JH9EqC6NS

         

Resources