» » » Here Fine-Grained Access to Network Services in Oracle Database 11g Release 1 Oracle allows access to external network services using several PL/SQL APIs ( UTLTCP, UTLSMTP, UTLMAIL, UTLHTTP and UTLINADDR), all of which are implemented using the TCP protocol. In previous versions of the database, access to external services was effectively an on/off switch based on whether a user was granted execute permissions on a specific package or not. Oracle 11g introduces fine grained access to network services using access control lists (ACL) in the XML DB repository, allowing control over which users access which network resources, regardless of package grants. Access control lists can be created, amended and deleted in the XML DB repository directly using FTP or WebDav. In addition, Oracle provide the DBMSNETWORKACLADMIN and DBMSNETWORKACLUTILITY packages to allow ACL management from PL/SQL.
Demos, Syntax, and Example Code of Oracle DBMSNETWORKACLADMIN. Access control lists are manipulated using the DBMSNETWORKACLADMIN package. The CREATEACL procedure uses the following parameters to create a new ACL: acl – The name of the access control list XML file, generated relative to the “/sys/acls” directory in the XML DB Repository. Description – A description of the ACL.
These APIs are the subject of this article. Related articles. Create an Access Control List (ACL) Access control lists are manipulated using the DBMSNETWORKACLADMIN package. The CREATEACL procedure uses the following parameters to create a new ACL:. acl - The name of the access control list XML file, generated relative to the '/sys/acls' directory in the XML DB Repository.
description - A description of the ACL. principal - The first user account or role being granted or denied permissions.
The text is case sensitive. isgrant - TRUE to grant, FALSE to deny the privilege. privilege - Use 'connect' for UTLTCP, UTLSMTP, UTLMAIL and UTLHTTP access. Use 'resolve' for UTLINADDR name/IP resolution.
The text is case sensitive. startdate - Default value NULL. When specified, the ACL will only be active on or after the specified date. enddate - An optional end date for the ACL.
The following code creates two test users to act as principals, then creates a new ACL. CONN sys/password@db11g AS SYSDBA CREATE USER test1 IDENTIFIED BY test1; GRANT CONNECT TO test1; CREATE USER test2 IDENTIFIED BY test2; GRANT CONNECT TO test2; BEGIN DBMSNETWORKACLADMIN.createacl ( acl = 'testaclfile.xml', description = 'A test of the ACL functionality', principal = 'TEST1', isgrant = TRUE, privilege = 'connect', startdate = SYSTIMESTAMP, enddate = NULL); COMMIT; END; / Once created, the ACL is visible in the 'directory. Additional users or roles are added to the ACL using the ADDPRIVILEGE procedure. Its parameter list is similar to the CREATEACL procedure, with the omission of the DESCRIPTION parameter and the addition of a POSITION parameter, which sets the order of precedence. BEGIN DBMSNETWORKACLADMIN.addprivilege ( acl = 'testaclfile.xml', principal = 'TEST2', isgrant = FALSE, privilege = 'connect', position = NULL, startdate = NULL, enddate = NULL); COMMIT; END; / Each principal is defined as a separate access control element (ACE), within the ACL. When multiple principles are defined, they are evaluated in order from top to bottom, with the last relevant reference used to define the privilege. This means a role that denies access to a resource can be granted to a user, but if the user is defined as a principal further down the file, that definition will override the role definition for that user.
Use the POSITION parameter to ensure privileges are evaluated in order. Privileges are removed using the DELETEPRIVILEGE procedure. If the ISGRANT or PRIVILEGE parameters are NULL, all grants or privileges for the ACL and principal are removed. BEGIN DBMSNETWORKACLADMIN.deleteprivilege ( acl = 'testaclfile.xml', principal = 'TEST2', isgrant = FALSE, privilege = 'connect'); COMMIT; END; / ACLs are deleted using the DROPACL procedure. BEGIN DBMSNETWORKACLADMIN.dropacl ( acl = 'testaclfile.xml'); COMMIT; END; / Assign an ACL to a Network Access control lists are assigned to networks using the ASSIGNACL procedure, whose parameters are listed below:. acl - The name of the access control list XML file.
host - The hostname, domain, IP address or subnet to be assigned. Hostnames are case sensitive, and wildcards are allowed for IP addresses and domains. lowerport - Defaults to NULL. Specifies the lower port range for the 'connect' privilege. upperport - Defaults to NULL.
If the lowerport is specified, and the upperport is NULL, it is assumed the upperport matches the lowerport. The code below shows the ACL created previously being assigned to a specific IP address and a subnet. BEGIN DBMSNETWORKACLADMIN.assignacl ( acl = 'testaclfile.xml', host = '192.168.2.3', lowerport = 80, upperport = NULL); DBMSNETWORKACLADMIN.assignacl ( acl = 'testaclfile.xml', host = '10.1.10.' , lowerport = NULL, upperport = NULL); COMMIT; END; / Only one ACL can be assigned to a specific host and port-range combination. Assigning a new ACL to a specific host and port-range results in the deletion of the previous assignment. You must take care when making a new assignment that you are not opening ports that were closed by a previous ACL assignment, or you could be opening yourself to attack.
When wildcard usage causes overlapping assignments, the most specific assignment will take precedence, so an ACL assigned to 192.168.2.3:80 takes precedence over once assigned to 192.168.2. etc. The UNASSIGNACL procedure allows you to manually drop ACL assignments. It uses the same parameter list as the ASSIGNACL procedure, with any NULL parameters acting as wildcards. BEGIN DBMSNETWORKACLADMIN.unassignacl ( acl = 'testaclfile.xml', host = '192.168.2.3', lowerport = 80, upperport = NULL); COMMIT; END; / ACL Views The DBANETWORKACLS, DBANETWORKACLPRIVILEGES and USERNETWORKACLPRIVILEGES views display the current ACL settings.
The expected output below assumes none of the delete/drop/unassign operations have been performed. The DBANETWORKACLS view displays information about network and ACL assignments. COLUMN host FORMAT A30 COLUMN acl FORMAT A30 SELECT host, lowerport, upperport, acl FROM dbanetworkacls; HOST LOWERPORT UPPERPORT ACL - - - - 10.1.10. /sys/acls/testaclfile.xml 192.168.2.3 80 80 /sys/acls/testaclfile.xml 2 rows selected. SQL The DBANETWORKACLPRIVILEGES view displays information about privileges associated with the ACL. COLUMN acl FORMAT A30 COLUMN principal FORMAT A30 SELECT acl, principal, privilege, isgrant, TOCHAR(startdate, 'DD-MON-YYYY') AS startdate, TOCHAR(enddate, 'DD-MON-YYYY') AS enddate FROM dbanetworkaclprivileges; ACL PRINCIPAL PRIVILE ISGR STARTDATE ENDDATE - - - - - - /sys/acls/testaclfile.xml TEST1 connect true 02-APR-2008 /sys/acls/testaclfile.xml TEST2 connect false 2 rows selected.
SQL The USERNETWORKACLPRIVILEGES view displays the current users network ACL settings. CONN test1/test1@db11g COLUMN host FORMAT A30 SELECT host, lowerport, upperport, privilege, status FROM usernetworkaclprivileges; HOST LOWERPORT UPPERPORT PRIVILE STATUS - - - - - 10.1.10. connect GRANTED 192.168.2.3 80 80 connect GRANTED 2 rows selected. SQL CONN test2/test2@db11g COLUMN host FORMAT A30 SELECT host, lowerport, upperport, privilege, status FROM usernetworkaclprivileges; HOST LOWERPORT UPPERPORT PRIVILE STATUS - - - - - 10.1.10. connect DENIED 192.168.2.3 80 80 connect DENIED 2 rows selected. SQL Checking Privileges In addition to the ACL views, privileges can be checked using the CHECKPRIVILEGE and CHECKPRIVILEGEACLID functions of the DBMSNETWORKACLADMIN package. CONN sys/password@db11g AS SYSDBA SELECT DECODE( DBMSNETWORKACLADMIN.checkprivilege('testaclfile.xml', 'TEST1', 'connect'), 1, 'GRANTED', 0, 'DENIED', NULL) privilege FROM dual; PRIVILE - GRANTED 1 row selected.
SQL COLUMN acl FORMAT A30 COLUMN host FORMAT A30 SELECT acl, host, DECODE( DBMSNETWORKACLADMIN.checkprivilegeaclid(aclid, 'TEST2', 'connect'), 1, 'GRANTED', 0, 'DENIED', NULL) privilege FROM dbanetworkacls; PRIVILE - DENIED 1 row selected. SQL The DBMSNETWORKACLUTILITY package contains functions to help determine possible matching domains. The DOMAINS table function returns a collection of all possible references that may affect the specified host, domain, IP address or subnet, in order of precedence. SELECT.
FROM TABLE(DBMSNETWORKACLUTILITY.domains('oel5-11g.localdomain')); COLUMNVALUE - oel5-11g.localdomain.localdomain. 3 rows selected. SQL SELECT. FROM TABLE(DBMSNETWORKACLUTILITY.domains('192.168.2.3')); COLUMNVALUE - 192.168.2.3 192.168.2. 192.168. 192. 5 rows selected.
SQL The DOMAINLEVEL function returns the level of the specified host, domain, IP address or subnet. SELECT DBMSNETWORKACLUTILITY.domainlevel('oel5-11g.localdomain') FROM dual; DBMSNETWORKACLUTILITY.DOMAINLEVEL('OEL5-11G.LOCALDOMAIN') - 2 1 row selected.
SQL SELECT DBMSNETWORKACLUTILITY.domainlevel('192.168.2.3') FROM dual; DBMSNETWORKACLUTILITY.DOMAINLEVEL('192.168.2.3') - 4 1 row selected. SQL These functions may be useful for when querying the ACL views for possible matches to a specific host, domain, IP address or subnet. SELECT host, lowerport, upperport, acl, DECODE( DBMSNETWORKACLADMIN.checkprivilegeaclid(aclid, 'TEST1', 'connect'), 1, 'GRANTED', 0, 'DENIED', null) PRIVILEGE FROM dbanetworkacls WHERE host IN (SELECT. FROM TABLE(DBMSNETWORKACLUTILITY.domains('10.1.10.191'))) ORDER BY DBMSNETWORKACLUTILITY.domainlevel(host) desc, lowerport, upperport; HOST LOWERPORT UPPERPORT ACL PRIVILE - - - - - 10.1.10. /sys/acls/testaclfile.xml GRANTED 1 row selected. SQL Test the ACL The TEST1 and TEST2 users have the ACL allowed and denied respectively.
This means we can test the ACL functionality by comparing their responses to calls to external network services. The following code grants execute permission on the UTLHTTP package to both users, then attempts to access a web page from each user. CONN sys/password@db11g AS SYSDBA GRANT EXECUTE ON UTLHTTP TO test1, test2; CONN test1/test1@db11g DECLARE lurl VARCHAR2(50):= 'lhttprequest UTLHTTP.req; lhttpresponse UTLHTTP.resp; BEGIN - Make a HTTP request and get the response. Lhttprequest:= UTLHTTP.beginrequest(lurl); lhttpresponse:= UTLHTTP.getresponse(lhttprequest); UTLHTTP.endresponse(lhttpresponse); END; / PL/SQL procedure successfully completed. SQL CONN test2/test2@db11g DECLARE lurl VARCHAR2(50):= 'lhttprequest UTLHTTP.req; lhttpresponse UTLHTTP.resp; BEGIN - Make a HTTP request and get the response. Lhttprequest:= UTLHTTP.beginrequest(lurl); lhttpresponse:= UTLHTTP.getresponse(lhttprequest); UTLHTTP.endresponse(lhttpresponse); END; / DECLARE.
ERROR at line 1: ORA-29273: HTTP request failed ORA-06512: at 'SYS.UTLHTTP', line 1029 ORA-24247: network access denied by access control list (ACL) ORA-06512: at line 7 SQL From this we can see that the TEST1 user was able to access the web page, while the TEST2 user was denied access by the ACL. The default action of the server is to deny access to external network service, as shown by the following test on a new user. CONN sys/password@db11g AS SYSDBA CREATE USER test3 IDENTIFIED BY test3; GRANT CONNECT TO test3; GRANT EXECUTE ON UTLHTTP TO test3; CONN test3/test3@db11g DECLARE lurl VARCHAR2(50):= 'lhttprequest UTLHTTP.req; lhttpresponse UTLHTTP.resp; BEGIN - Make a HTTP request and get the response. Lhttprequest:= UTLHTTP.beginrequest(lurl); lhttpresponse:= UTLHTTP.getresponse(lhttprequest); UTLHTTP.endresponse(lhttpresponse); END; / DECLARE. ERROR at line 1: ORA-29273: HTTP request failed ORA-06512: at 'SYS.UTLHTTP', line 1029 ORA-24247: network access denied by access control list (ACL) ORA-06512: at line 7 SQL This may cause some confusion when upgrading databases that access external network services from 10g to 11g. In these situations, it will be necessary to implement suitable access control lists before your original functionality is possible. Other Security Considerations commented on his and in his about the fact that the ACLs are not tied to a specific package.
This means opening a port on a server with the 'connect' privilege makes it accessible by UTLTCP, UTLSMTP, UTLMAIL and UTLHTTP. With this in mind there are some things to consider:. The use of fine-grained access to network services is not an excuse to ignore basic security measures, like on network service related packages. Control over the services you make available is possible by limiting access to the specific ports. If you only need HTTP access to port 80, specify the port rather than opening access to all ports on the server.
Wildcards can be dangerous as you may be granting access to more servers that you should. You must protect your ACLs. If people can alter them, they become useless as a protection mechanism. Prevent direct access to the ACLs in the XML DB repository and make sure users don't have access to the management APIs. Thanks to for his input. Open ACL From a security standpoint, it's not a good idea to allow complete network access from the database, but for testing features I sometimes find it useful to create an open ACL for an instance.
CONN / AS SYSDBA BEGIN DBMSNETWORKACLADMIN.createacl ( acl = 'openaclfile.xml', description = 'A test of the ACL functionality', principal = 'TEST', isgrant = TRUE, privilege = 'connect', startdate = SYSTIMESTAMP, enddate = NULL); DBMSNETWORKACLADMIN.assignacl ( acl = 'openaclfile.xml', host = '.' , lowerport = 1, upperport = 9999); COMMIT; END; / For more information see:. Hope this helps.
Installing PLSQL packages for DBMSNETWORKACLADMIN You can check whether they exist first, run this as user sys: select. from dbaobjects where name =. If they don't exist on Oracle RDBMS (I don't know whether maybe express edition excludes them, but that seems illogical), your database is not installed well. The easiest way is to re-install the database. In that case you don't need to replace the software, only create a new database.
The advanced way is to reinstall parts of the data dictionary. If you have never done it before, you can assume that the database will end up corrupt. You can try for instance executing?/dbs/catqm.sql.
By the path where ORACLEHOME lives and then rdbms/admin. Such as $ORACLEHOME/rdbms/admin on Linux. Remember to close the database for other users.
Maintaining ACL The extra comments led to the conclusion that ACL are missing. This is the approach I use to maintain them in a package. Please be careful, even 11.2.0.3 has a bad habit of often crashing the session of the connected user on ACL maintenance despite preventive measures. This script allows access to all ports between 1 and 32767.
You probably want to restrict this to applicable ports for your application. For ease of use I've pasted it here for all 32K ports. Maintenance of ACL can be non-trivial and can lead to security risks (which we gracefully accepted upto release 11 of Oracle:-). Involve your sysadmin or networkadmin in case of doubt. - When ORA-24247 errors continue despite creation of a network ACL, - first remove the ACL fully as user SYS using: - - begin - dbmsnetworkacladmin.dropacl('/sys/acls/invantive-producer.xml'); - end; - - This occurs incidentally on Oracle 11g R1.
prompt Create Access Control Lists. Declare lprincipal varchar2(30):= upper('&&itgenuserownerlogin'); lacl varchar2(300); laclfullpath varchar2(300); ldummy plsinteger; - - To temporary disable this code, sometimes it causes installation - issues. lskipaclmaintenance boolean:= false; - - To temporarily disable granting the ACL access. lskipaclgrants boolean:= false; begin lacl:= 'invantive-producer.xml'; laclfullpath:= '/sys/acls/' lacl; - if not lskipaclmaintenance then - - Drop superfluous network ACLs for users and roles that no longer exist. - Dropping network ACLs is tricky. Queries on the view dbanetworkacls - often lead to ORA-600. This query seems to work reliable on Oracle 11g R1.
- First delete all ACL privileges for which no ACL exists. During this, we will ignore problems. for r in ( select nae.acl, nae.principal from dbanetworkaclprivileges nae where nae.principal not in ( select usr.username from dbausers usr union all select rle.role from dbaroles rle ) ) loop begin dbmsnetworkacladmin.deleteprivilege ( r.acl, r.principal ); dbmsoutput.putline('Dropped superfluous ACL ' r.acl ' for ' r.principal '.'
); exception when others then dbmsoutput.putline('Ignoring error ' sqlerrm); end; end loop; - - Then try another time, not ignoring problems. for r in ( select nae.acl, nae.principal from dbanetworkaclprivileges nae where nae.principal not in ( select usr.username from dbausers usr union all select rle.role from dbaroles rle ) ) loop dbmsnetworkacladmin.deleteprivilege ( r.acl, r.principal ); dbmsoutput.putline('Dropped superfluous ACL ' r.acl ' for ' r.principal '.' ); end loop; - - Now create new network ACL when it does not yet exist. begin select 1 into ldummy from resourceview rvw where rvw.anypath = laclfullpath; dbmsoutput.putline('ACL ' lacl ' already present.
); exception when nodatafound then dbmsnetworkacladmin.createacl ( acl = lacl, description = 'Normal Access by Invantive Producer', principal = 'SYS', isgrant = true, privilege = 'connect', startdate = null, enddate = null ); dbmsnetworkacladmin.assignacl ( acl = lacl, host = '.' , lowerport = 1 /.
ATTENTION! You may want to tighten this!./, upperport = 32767 /. ATTENTION! You may want to tighten this!./ ); dbmsoutput.putline('Created ACL ' lacl ' for port 1 till 32767.'
); end; else dbmsoutput.putline('Skipped maintenance of Access Control Lists.' ); end if; - if not lskipaclgrants then - - Update the privilges for the ACL when not correct. for rusr in ( select lprincipal principal from dual union all - - Any unspecified Invantive schema. - For SYS, itgenschemasr can contain multiple rows. select smar.name principal from itgenschemasr smar ) loop begin select 1 into ldummy from dbanetworkaclprivileges nae where nae.acl = laclfullpath and nae.principal = rusr.principal and nae.privilege = 'connect' and nae.isgrant = 'true' and nae.invert = 'false' and nae.startdate is null and nae.enddate is null; dbmsoutput.putline('Connect privileges already granted to ' lprincipal '.
); exception when nodatafound then dbmsnetworkacladmin.addprivilege ( acl = lacl, principal = lprincipal, isgrant = true, privilege = 'connect', startdate = null, enddate = null ); dbmsoutput.putline('Connect privileges granted to ' lprincipal '.' ); end; end loop; - commit; else dbmsoutput.putline('Skipped grants of Access Control Lists.' ); end if; end; /.