首页 > 解决方案 > 使用 DBMS_CRYPTO 但表存在时出现奇怪的 ORA-942

问题描述

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

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;

这是一个 PLSQL 包,其模式名为ATLED

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:表或视图不存在

引用的表确实存在。

对 proc 的调用p1确认与 IMP_FULL_DATABASE 捆绑的所有权限都存在,包括CREATE ANY TABLE, DROP ANY TABLE, EXECUTE 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 TABLEstmt 以删除DBMS_CRYPTO呼叫,它也可以正常工作。

CREATE TABLE调用的实际包/过程在如上运行时会创建许多表,但在任何stmt中调用 DBMS_CRYPTO 的情况下会失败。

如果我直接授予batch用户CREATE ANY TABLE,SELECT ANY TABLEEXECUTE ANY PROCEDUREprivs 并直接将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;
/

然后将stmtDBMS_CRYPTO.HASH(cc,2)中的替换为then 就可以了!!!CREATE TABLEbatch.crypto_hash(cc)

因此,对于被引用的表的授权肯定不是问题,但更可能是 DBMS_CRYPTO 工作方式的内部问题。也许它在某处读取了一个查找表。在此之前我也尝试过GRANT EXECUTE ON UTL_I18N to batch,但没有奏效。

所以我有一个解决方法,但我仍然想知道为什么会发生这种情况。

标签: oracleplsqloracle12cuser-roles

解决方案


你这样做:

... FROM ARCHIVE.table_b

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

  1. 通过角色
  2. 直接地

如果您通过角色授予特权,它可以工作——但不适用于命名的 PL/SQL 过程。它将在匿名 PL/SQL 中工作,但不能在过程、函数、包中工作,所以 - 检查并可能直接授予SELECTtable_b用户。


推荐阅读