1

We have an application in our organization that is based on Oracle Forms 11g (on Oracle Fusion Middleware/WLS). Users have access to the application through accounts created at the database (i.e. they exist in dba_users). Each user is assigned a specific role based on their area of work and they use the user id to log on to the application. The user may have read/write access to certain functionality in the application and for this their roles have the following permissions-

EXECUTE ANY LIBRARY 
SELECT ANY SEQUENCE 
EXECUTE ANY TYPE 
EXECUTE ANY PROCEDURE 
UPDATE ANY TABLE 
SELECT ANY TABLE 
DELETE ANY TABLE 
EXECUTE ANY INDEXTYPE 
INSERT ANY TABLE 

Now we have some users requesting for SQL Client access (i.e. TNS settings) so that they can connect to the DB and perform queries for their research. These business users are ofcourse knowledgeable in SQL but we want to restrict their access based on the type of client they use to log on to the database. Any client other than the application itself, should restrict them to "read only".

Is there a way to achieve this?

asked Feb 26, 2015 at 23:52
5
  • Not possible. The name of the client is provided by the client itself - so the client can pretend to be sqlplus or sqldeveloper or annjawan. You have to restrict this through the user account, it's the only safe way. Commented Feb 27, 2015 at 0:03
  • But we know the Application client's name. Can we restrict it like if not <app_client> then... perhaps through a BEFORE LOGON trigger? We also know the Machine Name which will always be the Application server name if the user is using the Application, that can be used as well? Commented Feb 27, 2015 at 0:09
  • I can connect with a different client pretending to be <app_client> without any problems. You can also change the value that shows up in machine in v$session (those are simply connection properties for a JDBC connection for example). You might be able to check the IP address in a logon trigger, but I'm not sure about that. The only (really: the only) safe way to restrict access is through privileges on the user account. Commented Feb 27, 2015 at 0:19
  • Yes, I figured that is the only safe way but revoking access privilege will mean revoke privileges from the application too, which we don't want to do. I don't think the users are that smart to be changing their connection properties ;) but the question is will a BEFORE LOGON trigger with revoke command work? Commented Feb 27, 2015 at 0:28
  • The only way to do this is to create separate read-only users. A given user cannot have two seperate sets of grants. Commented Feb 27, 2015 at 7:59

1 Answer 1

3

You can check it with a database trigger, for example:

CREATE ROLE ROLE_POWER_USER NOT IDENTIFIED;
CREATE OR REPLACE TRIGGER LOG_T_LOGON 
 AFTER LOGON ON DATABASE
DECLARE
 
 osUser VARCHAR2(30);
 machine VARCHAR2(100); 
 prog VARCHAR2(100)
 ip VARCHAR2(15);
 
BEGIN
 
 IF ora_login_user IS NULL THEN 
 RETURN;
 END IF;
 
 SELECT OSUSER, MACHINE, PROGRAM, ora_client_ip_address
 INTO osUser, machine, prog, ip
 FROM V$SESSION 
 WHERE SID = SYS_CONTEXT('USERENV', 'SID');
 
 IF NOT DBMS_SESSION.IS_ROLE_ENABLED('ROLE_POWER_USER') THEN 
 IF LOWER(prog) <> 'your_application_name.exe' THEN
 RAISE_APPLICATION_ERROR(-20000, 'Logon denied: You must use only the official client application');
 END IF;
 ELSE
 IF LOWER(prog) NOT IN ('sqlplus.exe', 'toad.exe') THEN
 RAISE_APPLICATION_ERROR(-20000, 'Logon denied: You must use only SQL*Plus or TOAD for you private queries');
 END IF; 
 END IF;
 -- Successful login, continue as normal
END;
/

You can also check other conditions like IP-Address or the machine name.

SELECT privileges on tables and views you have to grant to the user or ROLE in the "classic" way. This trigger only prevents to logon to the database with certain tools.

Note, a user with System Privilege ADMINISTER DATABASE TRIGGER (for example DBA role, or SYS of course) never get the exception, i.e. they can logon to the database in any case and you cannot block this by the trigger.

Another note: This trigger is insecure! For example you can simply make a copy of your local sqlplus.exe and name it your_application_name.exe. Then this trigger would allow to use it.

With JDBC it is even a simple property you can set, see https://stackoverflow.com/questions/42027389/programatically-set-vsession-program-property

answered Feb 27, 2015 at 9:09
2
  • 1
    I don't need to make a copy of sqlplus.exe to connect using your_application_name.exe. In a JDBC client this is a simple configuration property (so is machine name or OS user) Commented Feb 27, 2015 at 13:21
  • @wernfried This trigger worked pretty nicely. We did some changes to it to include checking the user PROFILE and instead of checking the program we check the MACHINE from where the conncection is coming from. Our Application always connects from the App Server Machine id even when User logs on to the app from their PC and that server machine id will not change (ever). So that solves the program name problem. Commented Mar 9, 2015 at 19:52

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.