sábado, 1 de noviembre de 2008

¿Cómo ocultar código fuente PL/SQL? Use Wrap.

Imaginemos un escenario en el cual hemos desarrollado un procedimiento almacenado en PL/SQL y deseamos evitar que alguien, incluido el DBA, pueda ver y/o modificar el código fuente. ¿Es eso posible?, definitivamente sí: Oracle provee el utilitario Wrap para lograrlo, pero implicaba invocarlo desde el Sistema Operativo; a partir de 10g es posible invocarlo desde dentro de la base de datos. Veamos cómo hacer uso de ambas modalidades.

Primero un vistazo al código que me interesa ocultar:
[oracle@caliope ~]$ cat salary.sql
CREATE OR REPLACE
FUNCTION salary (
empno emp.empno%TYPE )
RETURN NUMBER
IS
sal emp.sal%TYPE;
BEGIN
SELECT sal INTO salary.sal
FROM emp
WHERE empno = salary.empno;
RETURN ( salary.sal );
END;

La primera alternativa es usar el utilitario Wrap desde el Sistema Operativo.
  1. Hay que invocarlo referenciando al archivo que contiene el código fuente.
  2. [oracle@caliope ~]$ wrap iname=salary.sql
    
    PL/SQL Wrapper: Release 10.2.0.4.0- Production on Sat Nov 01 14:21:47 2008
    
    Copyright (c) 1993, 2004, Oracle.  All rights reserved.
    
    Processing salary.sql to salary.plb
  3. Verificamos el resultado.
  4. [oracle@caliope ~]$ cat salary.plb
    CREATE OR REPLACE
    FUNCTION salary wrapped
    a000000
    367
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    8
    cc d6
    +/IgG5qcUWhn5W4aX1Z1gJbmalUwgy5KLcvWfHSi2sHVSCY2DKrK4KYn8hQGyrdN4JG7orD5
    ELaEY9EXT7sxm8hT0NF8GQX2BSRNdGc/i2nS6FUq4oJr3+Z/vda3u1pli6dW3SXcl4vlGtfr
    ShxK0Ikb/IzmSgsWLtX2Nyo5Ob28iiwzrfFQOmdO1j2jRP8s5Z3aTTuovLrHOuGA3Hyl
    
    /
  5. Introducimos el código en la base de datos.
  6. [oracle@caliope ~]$ sqlplus scott/tiger @salary.plb
    
    SQL*Plus: Release 10.2.0.4.0 - Production on Sat Nov 1 14:23:59 2008
    
    Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.
    
    
    Connected to:
    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production
    With the Partitioning, OLAP, Data Mining and Real Application Testing options
    
    
    Function created.
  7. Comprobamos que la funcion está operativa.
  8. SCOTT@orcl > select salary( 7654 ) from dual;
    
    SALARY(7654)
    ------------
    1312.5
    
    SCOTT@orcl >

Como resultado tenemos ahora un procedimiento almacenado cuyo código fuente es ininteligible a simple vista.

¿Qué hacer si el código ya está en la base de datos? Pues podemos extraerlo a un archivo y seguir el procedimiento previo, pero tambien es posible hacer uso del mejorado package DBMS_DDL, entonces manos a la obra.
  1. Usaremos la siguiente rutina para transformar el código fuente.
  2. [oracle@caliope ~]$ cat wrapped.sql
    DECLARE
    v_source DBMS_SQL.VARCHAR2A;
    BEGIN
    v_source(1) := 'CREATE OR REPLACE ';
    FOR s IN ( SELECT line, text
    FROM user_source
    WHERE name = 'SALARY'
    ORDER BY line )
    LOOP
    v_source(s.line+1) := s.text;
    END LOOP;
    dbms_ddl.create_wrapped(
    ddl => v_source,
    lb => 1,
    ub => v_source.count );
    END;
  3. Ahora lo ejecutamos.
  4. SCOTT@orcl > @wrapped
    
    PL/SQL procedure successfully completed.
  5. Verificamos que el código fuente fue modificado.
  6. SCOTT@orcl > select text from user_source
    2  where name = 'SALARY' order by line;
    
    TEXT
    --------------------------------------------------------------------------------
    FUNCTION salary wrapped
    a000000
    369
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    abcd
    8
    c3 d2
    NL5qz7Eyn6/UUHrpUacIYXrnSkQwgy7wLcsVfHSiWHOUxMoNmSQvf6CVAlrwXr70aca5WXwI
    /nAKWlYzkLkxeCuI8kessTO0QSAhNtwDkRNJ6sbC/1+niQxcN3d3A9MG5qanSMCbmJCZRkFk
    zHqG9AcGWonxLvVFqyc+fCfcn4q5PwtD7ZLkhFU52f6bi7u9g2dWnLjOpqUrlos=
  7. Finalmente veamos si está operativo.
  8. SCOTT@orcl > select salary( 7654 ) from dual;
    
    SALARY(7654)
    ------------
    1312.5

Nuevamente el objetivo se ha cumplido!

En conclusión, hemos visto dos formas de transformar nuestro código fuente en un texto indescifrable apoyados de Wrap. El código mostrado no está libre de errores ni está optimizado, pero les puede servir como una base. Ah!, y no olviden darle una ojeada a la documentación, para que tengan un panorama completo de las posibilidades existentes.

Posts Relacionados:

¿Te pareció interesante este artículo?, ¿te quedaron algunas dudas?, ¿quieres sugerirme un tema a tratar?, pues déjame tus comentarios o envíame un email y para que NO te pierdas ningún Post, suscríbete por email ahora mismo!

2 comentarios, agrega el tuyo!

Unknown dijo...

Hola Kike; una consulta, esto altera en alguna manera la performance de nuestros objetos?

Enrique Orbegozo dijo...

Hola Ulises, usar Wrap no afecta el desempeño, de hecho cada vez que Oracle compila un stored procedure lo termina escribiendo en el mismo formato que wrap nos proporciona, puedes leer http://www.blackhat.com/presentations/bh-usa-06/BH-US-06-Finnigan.pdf donde explican estas internalidades e incluso una potencial forma de revertir lo hecho por Wrap.

Enrique