Friday, 26 August 2011

Ways to hide your code

Question:
I want to allow everyone to run my procedures and functions, but I don't want them to be able to see the code behind the program header. How can I accomplish that?
Answer:
Oracle offers two ways to hide your code:
1. "Wrap" or obfuscate your code so that it can still be compiled and executed, but cannot be read
2. Hide program implementations within a package body
Wrapping is certainly the best way to ensure that others cannot read your code, even if they connect to the schema that owns the code. However, it does have drawbacks. Let's take a look at both options.
To wrap your code, call the wrap executable. Suppose, for example, that I start with the following procedure definition in the file before_wrap.sql:
CREATE OR REPLACE PROCEDURE my_procedure
IS
BEGIN
DBMS_OUTPUT.put_line ( 'running my_procedure' );
END my_procedure;
/
I then call the wrap executable as follows:
wrap iname=before_wrap.sql oname=after_wrap.plb
The after_wrap.plb file (plb is a rough-hewn acronym for "PL/SQL Binary" and is the standard extension used by Oracle for its wrapped code) then contains the following text:
CREATE OR REPLACE PROCEDURE my_procedure wrapped
a000000
b2
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
7
66 96
JglYKBnago+nNjoDigwhI233Q8Ywg5nnm7+fMr2ywFyl8F8oqVJTeta+bnFVAHNTjo6OcW7P
1oZzhITh5oTSqVcZxutyXDWENe1NIZaWgpZMqMRlvA4WJK0qY6AWXEw16+zZPXJElSH2OaY9
CKRI

/
While that doesn't look anything like PL/SQL code, you can compile it into the database and execute the program, just as you would if it were not wrapped. For example:
SQL> @after_wrap.plb

Procedure created.

SQL> exec my_procedure
running my_procedure
For more information about Oracle's obfuscation capabilities, read the documentation.
By the way, in Oracle Database 10g Release 2, you can use the DBMS_DDL package to obfuscate PL/SQL program units that are created dynamically (at run-time).
Obfuscation is very handy for independent software vendors who need to hide their proprietary code from the prying eyes of competitors. It is less obvious that one should use it as a general mechanism to hide code from other developers in your organization.
The problem with obfuscating your code is that no one can read the source code in the database, even the owner of the code, even those who need to debug the code to fix problems.
If you would like to compile your program into the database so that the owner of the program can read and work with code, but others (who are allowed to run the program) cannot see the implementation, you should define your programs in packages.
If you implement your functionality in schema-level (a.k.a, stand-alone) procedures and functions, then granting execute authority also allows programmers connected to other schema to see the source code of those program units. This fact is demonstrated below:
SQL> CONNECT scott/tiger
Connected.
SQL> CREATE OR REPLACE PROCEDURE my_procedure
2 IS
3 BEGIN
4 DBMS_OUTPUT.put_line ( 'my_procedure' );
5 END my_procedure;
6 /

Procedure created.

SQL> GRANT EXECUTE ON my_procedure TO hr
2 /

Grant succeeded.

SQL> CONNECT hr/hr
Connected.
SQL> SELECT TYPE, text
2 FROM all_source
3 WHERE owner = 'SCOTT' AND NAME = 'MY_PROCEDURE'
4 ORDER BY TYPE, line
5 /

TYPE TEXT
-------------------- -----------------------------------------------
PROCEDURE PROCEDURE my_procedure
PROCEDURE IS
PROCEDURE BEGIN
PROCEDURE DBMS_OUTPUT.put_line ( 'my_procedure' );
PROCEDURE END my_procedure;
Suppose that you instead implement your procedures and functions within a package. You then can grant execute authority on that package to other schemas. Users connected to those schemas will be able to only see the package specifications, and not the bodies. This fact is demonstrated below:
SQL> CONNECT scott/tiger
Connected.
SQL> CREATE OR REPLACE PACKAGE my_package
2 IS
3 PROCEDURE hidden_implementation;
4 END my_package;
5 /

Package created.

SQL> CREATE OR REPLACE PACKAGE BODY my_package
2 IS
3 PROCEDURE hidden_implementation
4 IS
5 BEGIN
6 DBMS_OUTPUT.put_line ( 'hidden_implementation' );
7 END hidden_implementation;
8 END my_package;
9 /

Package body created.

SQL> GRANT EXECUTE ON my_package TO hr
2 /

Grant succeeded.

SQL> CONNECT hr/hr
Connected.
SQL> SELECT TYPE, text
2 FROM all_source
3 WHERE owner = 'SCOTT' AND NAME = 'MY_PACKAGE'
4 ORDER BY TYPE, line
5 /

TYPE TEXT
-------------------- ----------------------------------------------
PACKAGE PACKAGE my_package
PACKAGE IS
PACKAGE PROCEDURE hidden_implementation;
PACKAGE END my_package;
Notice that none of the lines from the package body are visible through ALL_SOURCE.

No comments:

Post a Comment