Showing posts with label cat. Show all posts
Showing posts with label cat. Show all posts

Sunday, June 01, 2014

Wrap Utility

This is an example using the wrap utility, which allows you to hide stored code. Software suppliers can use it to prevent customers stealing their PL/SQL. First I created a table:
 
SQL> create table name_list
  2  as select 'ANDREW' name from dual
  3  /
 
Table created.
 
SQL> select * from name_list
  2  /
 
NAME
------
ANDREW
 
SQL>
 
Then I created a procedure to add names to the table:
 
SQL> create or replace procedure add_name
  2   (new_name char) as
  3  begin
  4   insert into name_list values(new_name);
  5  end;
  6  /
 
Procedure created.
 
SQL>
 
... and I tested it as follows:
 
SQL> execute add_name('BRIAN');
 
PL/SQL procedure successfully completed.
 
SQL> select * from name_list
  2  /
 
NAME
------
ANDREW
BRIAN
 
SQL>
 
The procedure was easy to see in the database so anybody could have stolen it:
 
SQL> l
  1  select text from dba_source
  2  where name = 'ADD_NAME'
  3* order by line
SQL> /
 
TEXT
-------------------------------------------------------
procedure add_name
(new_name char) as
begin
insert into name_list values(new_name);
end;
 
SQL>
 
The wrap utility was stored here:
 
ORACLE11 > which wrap
/oracle/app/oracle/product/11.2.0/bin/wrap
ORACLE11 >
 
I ran it on the source code. To do this you supply the name of the file containing the code to be wrapped as the iname parameter and the name of the file to store the wrapped code as the oname parameter:
 
ORACLE11 > cat procedure.sql
create or replace procedure add_name
(new_name char) as
begin
insert into name_list values(new_name);
end;
/
ORACLE11 > wrap iname=procedure.sql \
> oname=wrapped_procedure.sql
 
PL/SQL Wrapper: Release 11.2.0.1.0- 64bit Production on Thu Nov 03 13:07:53 2011
 
Copyright (c) 1993, 2009, Oracle.  All rights reserved.
 
Processing procedure.sql to wrapped_procedure.sql
ORACLE11 >
 
This encrypted the source code as follows:
 
ORACLE11 > cat wrapped_procedure.sql
create or replace procedure add_name wrapped
a000000
1
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
7
5b 92
d6K98qP2M1tFArx52RBb3rXsyPgwg5nnm7+fMr2ywFxaWaH0cgxHLkMJUKXHstD+x9IyXLgz
uHQlw7h0i8DAMv7Shgml0pmfsp77Caj5nspECCJBr6ieOEoia+KvuEzsPHHiP9E8dKYY7AS4
 
/
ORACLE11 >
 
I compiled the wrapped source code and checked that it was still encrypted in the database:
 
SQL> @wrapped_procedure
 
Procedure created.
 
SQL> select text from dba_source
  2  where name = 'ADD_NAME'
  3  order by line
  4  /
 
TEXT
-------------------------------------------------------
procedure add_name wrapped
a000000
1
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
abcd
7
5b 92
d6K98qP2M1tFArx52RBb3rXsyPgwg5nnm7+fMr2ywFxaWaH0cgxHLkM
JUKXHstD+x9IyXLgz
uHQlw7h0i8DAMv7Shgml0pmfsp77Caj5nspECCJBr6ieOEoia+KvuEz
sPHHiP9E8dKYY7AS4
 
SQL>
 
Finally, I checked that the procedure still worked:
 
SQL> execute add_name('COLIN');
 
PL/SQL procedure successfully completed.
 
SQL> select * from name_list
  2  /
 
NAME
------
ANDREW
BRIAN
COLIN
 
SQL>
 
Looking elsewhere on the Internet there seem to be a few points to bear in mind when using wrap. I have not checked any of these myself:
  1. It will increase the size of your source code.
  2. If you have strict security on $ORACLE_HOME/bin, you may wish to install a copy of wrap in a shared area for your developers.
  3. You should use the correct version of wrap for your database. Otherwise, if Oracle has introduced some new feature, an out of date version of wrap will not recognise it.
  4. You should only wrap package bodies. You should leave the package headers alone as they can provide useful documentation (I'm not sure if I agree with this one).

Sunday, June 24, 2012

Error Handling in SQL*Plus

If you want to know if there has been an error in a SQL*Plus session, you need to do this explicitly. Here is a UNIX shell script:

ORACLE 11 > cat error1.ksh
sqlplus / << failure
select to_number('A') from dual
/
exit
failure
echo "Return code after failure = $?"
ORACLE 11 >

When you run it, there is a failure in the SQL*Plus session but UNIX is not aware of this:

ORACLE 11 > ./error1.ksh

SQL*Plus: Release 11.2.0.1.0 Production on Wed Jun 20 14:41:54 2012

Copyright (c) 1982, 2009, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL>   2  select to_number('A') from dual
                 *
ERROR at line 1:
ORA-01722: invalid number

SQL> Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Return code after failure = 0
ORACLE 11 >

If you wish to tell UNIX there has been an error, you should add whenever sqlerror exit failure to the SQL*Plus session:

ORACLE 11 > cat error2.ksh
sqlplus / << failure
whenever sqlerror exit failure
select to_number('A') from dual
/
exit
failure
echo "Return code after failure = $?"
ORACLE 11 >

Then the return code will be non zero so UNIX will know about the error:

ORACLE 11 > ./error2.ksh

SQL*Plus: Release 11.2.0.1.0 Production on Wed Jun 20 14:45:44 2012

Copyright (c) 1982, 2009, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> SQL>   2  select to_number('A') from dual
                 *
ERROR at line 1:
ORA-01722: invalid number

Disconnected from Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
Return code after failure = 1
ORACLE 11 >