使用DBMS_CRYPTO但表存在时奇怪的ORA-942

时间:2019-01-17 01:12:12

标签: oracle plsql oracle12c user-roles

这很奇怪,而且不容易解释,所以请多多包涵。

Linux x86_64上的Oracle 12.2.0.1。

我们有一个名为BATCH的用户,该用户具有最小权限。

CREATE USER batch IDENTIFIED BY batch
  DEFAULT TABLESPACE users
  QUOTA UNLIMITED ON users;

GRANT CREATE SESSION TO batch;
GRANT EXECUTE ON DBMS_CRYPTO TO batch;

这是一个名为ATLED的架构中的PLSQL程序包,它是:

CREATE OR REPLACE PACKAGE ALTED.the_pkh AUTHID current_user AS
   PROCEDURE crttab;
END;
/

CREATE OR REPLACE PACKAGE BODY ALTED.the_pkh AS
   PROCEDURE crttab IS
   BEGIN
      EXECUTE IMMEDIATE 'CREATE TABLE atled.the_tab AS SELECT id, DBMS_CRYPTO.HASH(cc,2) AS cc FROM ARCHIVE.table_b';
   END crttab;
END;
/

我们正在使用基于代码的访问控制(CBAC-12c功能)来限制/控制/允许其他没有牙齿的用户执行某些固定操作,因此我们创建了一个包装程序,并赋予了高度特权角色,然后将执行权限授予批处理用户:

CREATE OR REPLACE PROCEDURE ALTED.wrapper_crttab AS
   PROCEDURE p1 IS
      CURSOR c1 is SELECT * FROM SESSION_PRIVS;
   BEGIN
      FOR r1 IN c1 LOOP
         DBMS_OUTPUT.PUT_LINE( r1.privilege );
      END LOOP;
   END;
BEGIN
   p1;
   ALTED.the_pkh.crttab;
END;
/

GRANT IMP_FULL_DATABASE TO ALTED;
GRANT IMP_FULL_DATABASE ALTED.wrapper_crttab;
GRANT EXECUTE ON ALTED.wrapper_crttab TO batch;

现在运行它:

CONN batch/batch
SET SERVEROUTPUT ON
EXEC ALTED.wrapper_crttab;

这会导致错误:

  

第1行出现错误:
  ORA-00942:表或视图不存在

引用的表确实存在。

p1 proc的调用确认存在与IMP_FULL_DATABASE捆绑在一起的所有特权,包括CREATE ANY TABLEDROP ANY TABLEEXECUTE ANY PROCEDURE

如果我这样做:

GRANT CREATE ANY TABLE TO batch;
GRANT SELECT ANY TABLE TO batch;

CONN batch/batch

EXEC EXECUTE IMMEDIATE 'CREATE TABLE atled.the_tab AS SELECT id, DBMS_CRYPTO.HASH(cc,2) AS cc FROM ARCHIVE.table_b;

这有效。

如果我更改CREATE TABLE stmt以删除DBMS_CRYPTO调用,它也将正常工作。

所调用的实际包/过程按上面的方式运行时会创建许多表,但是在任何CREATE TABLE语句中调用DBMS_CRYPTO的情况下都会失败。

如果我直接向batch用户授予CREATE ANY TABLESELECT ANY TABLEEXECUTE ANY PROCEDURE privs权限,并直接成批运行CREATE TABLE命令,那么它也可以工作。

所以这不是(我认为)直接的ORA-942错误,而是与DBMS_CRYPTO特权链有关的东西,并且仅在程序包存储过程中执行时才发生,但是我不知道到底是什么。

更新1

如果我为DBMS_CRYPTO.HASH创建包装,如下所示:

CREATE OR REPLACE FUNCTION batch.crypto_hash ( pcc IN CLOB ) RETURN VARCHAR2 IS
BEGIN
   RETURN DBMS_CRYPTO.HASH(pcc,2);
END;
/

然后将DBMS_CRYPTO.HASH(cc,2) stmt中的CREATE TABLE替换为batch.crypto_hash(cc),就可以了!!!

因此,绝对不是引用表的授予问题,而是DBMS_CRYPTO工作方式的内部问题。也许它在某处读取查询表。在此之前,我也尝试过GRANT EXECUTE ON UTL_I18N to batch,但这没用。

所以我有一个解决方法,但是woudl仍然想知道为什么会这样。

1 个答案:

答案 0 :(得分:0)

您正在这样做:

... FROM ARCHIVE.table_b

应该从该表中选择的用户必须具有SELECT特权。可以授予

  1. 通过角色
  2. 直接

如果您通过角色授予了特权,则可以使用-但不适用于命名的PL / SQL过程。它可以在匿名PL / SQL中工作,但不能在过程,函数,程序包中工作,因此-请检查并可能将SELECT上的table_b授予该用户。