PL/SQL 中的 Oracle DBMS_LDAP.open_ssl 显示错误:ORA-31202:SSL 握手失败
Posted
技术标签:
【中文标题】PL/SQL 中的 Oracle DBMS_LDAP.open_ssl 显示错误:ORA-31202:SSL 握手失败【英文标题】:Oracle DBMS_LDAP.open_ssl in PL/SQL shows error: ORA-31202: SSL handshake failed 【发布时间】:2017-01-15 19:14:51 【问题描述】:我们已切换到新的 Microsoft ADFS 服务器,现在我们必须使用 LDAPS(端口 636 上的 LDAP over SSL)。但是在 PL/SQL 包中通过添加 DBMS_LDAP.open_ssl (基于 here )我得到:
ORA-31202: DBMS_LDAP: LDAP client/server error: SSL handshake failed
我的故障排除指导我对连接进行 tcpdump 调试,我发现 Oracle (12.1.0.2) DBMS_LDAP 在 SSL 握手上仅使用以下三个密码套件,这些密码套件都非常旧且不安全,并且不受最新的 Microsoft AD 支持。即使我用 ldap.google.com:636 尝试了另一个 12c db (12.1.0.2.0) 并收到相同的错误和相同的密码套件。
Version: TLS 1.2 (0x0303)
Cipher Suite: TLS_DH_anon_WITH_3DES_EDE_CBC_SHA (0x001b)
Cipher Suite: TLS_DH_anon_WITH_RC4_128_MD5 (0x0018)
Cipher Suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00ff)
Oracle 知识表明,很多人都曾遇到过这个问题(文档 ID 19285025.8,文档 ID 1561121.1),唯一的建议是补丁“19285025”。我们已经完成了这个补丁,但仍然没有进展。我们找到了 Oracle 文档 (here) 来展示如何通过“netmagr”配置安全套接字层和添加密码套件,但最后我知道这仅适用于 oracle DB 连接,但没有影响。 现在的问题是? 1. DBMS_LDAP.open_ssl 这个“SSL 握手失败”如何解决?我们如何为 DBMS_LDAP.open_ssl 设置不同的密码套件? 2. 使用 LDAPS 的任何替代 PL/SQL 包?或者我们必须使用 Java 包并将其加载到 DB 中?
【问题讨论】:
恕我直言,我认为这是一个编程问题,因为整个故事都是关于在PL/SQL 编程中使用LDAPS。我还询问了我使用 Java 过程找到的替代解决方案,并将很快作为我的答案。 【参考方案1】:我已切换到 java 程序而不是 Oracle DBMS_LDAP。它运行良好,不再存在 SSL 问题(除了 java 的扩展功能之外)。
SET SERVEROUTPUT ON SIZE 5000;
CALL dbms_java.set_output(5000);
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED LDAP AS
import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;
/**
* Java LDAP Package by ATK, 9/9/2016
*/
class ldap
public static int ldap_auth(String username, String my_password, String ldap_server)
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldap_server ); //example "ldap://ldap.yourcompany.com:636"
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid=" + username + ",OU=users,DC=company,DC=com");
env.put(Context.SECURITY_CREDENTIALS, my_password);
try
// Create initial context
DirContext ctx = new InitialDirContext(env);
System.out.println("Connection Successful.");
ctx.close();
return 0;
catch (NamingException e)
System.out.println("LDAP Connection: FAILED");
e.printStackTrace();
return -1;
;
--show errors java source ldap ; -- to check class compile
CREATE OR REPLACE FUNCTION ldap_auth (username in varchar2, my_password in varchar2, ldap_server in varchar2) RETURN NUMBER
AS LANGUAGE JAVA
NAME 'ldap.ldap_auth (java.lang.String, java.lang.String, java.lang.String) return int';
call dbms_java.grant_permission( 'MySchema', 'SYS:java.net.SocketPermission', 'ldap.companyDomain.com', 'resolve' );
call dbms_java.grant_permission( 'MySchema', 'SYS:java.net.SocketPermission', 'ldapqa.companyDomain.com', 'resolve' );
call dbms_java.grant_permission( 'MySchema', 'SYS:java.net.SocketPermission', 'ldapdev.companyDomain.com', 'resolve' );
call dbms_java.grant_permission( 'MySchema', 'SYS:java.net.SocketPermission', '10.14.10.53:636', 'connect,resolve' );
call dbms_java.grant_permission( 'MySchema', 'SYS:java.net.SocketPermission', '10.14.10.54:636', 'connect,resolve' );
call dbms_java.grant_permission( 'MySchema', 'SYS:java.net.SocketPermission', '10.14.10.55:636', 'connect,resolve' );
现在您可以使用以下方法对其进行测试:
SET SERVEROUTPUT ON SIZE 5000
CALL dbms_java.set_output(0);
declare
l_ret int ;
begin
l_ret := ldap_auth ('myUser', 'myPassword', 'ldap://lds.companyDomain.com:636');
DBMS_OUTPUT.put_line('Return = ' || l_ret );
end;
【讨论】:
【参考方案2】:我很欣赏这是一篇旧帖子,但作为参考,事实证明 DBMS_LDAP 所宣传的密码套件依赖于 open_ssl 函数的 sslauth
参数。
当sslauth
设置为1
(无身份验证)时,将只通告TLS_DH_anon_xxx
密码套件。
当使用 2
或 3
(1 或 2 路身份验证)时,所有密码套件都将被宣传(OCI 中的 vanilla 19c ATP 数据库中的 25 个套件)
【讨论】:
以上是关于PL/SQL 中的 Oracle DBMS_LDAP.open_ssl 显示错误:ORA-31202:SSL 握手失败的主要内容,如果未能解决你的问题,请参考以下文章
Oracle:使用 SQL 或 PL/SQL 查找动态 SQL 中的错误位置
Oracle Apex:PL/SQL 块中的 Javascript 代码