2016-11-19 33 views
0

PL/SQLを使用してWindowsサーバー上のOracle 11gで実行されているアプリケーションのSSL保護されたLDAPサーバーに対して内部的に認証しようとしています。証明書をウォレットにロードしてd:\ wallets \に格納し、有効であることをoracle wallet manager(ewallet.p12が正しく構成されたパスワードで開きます)にロードされていることを確認できます。しかし、私が何をしても、PL/SQL関数を使用して作業することはできません。ここでは、コードは次のようになります。Oracle PL/SQL LDAP - ウォレットを開くことができません

create or replace FUNCTION ldap_auth(
    p_username IN VARCHAR2, 
    p_password IN VARCHAR2 
) 
RETURN varchar2 IS 
    l_ldap_host   VARCHAR2(256) := 'ldapserver.internal.net'; 
    l_ldap_port   number := 636; 
    l_dn      VARCHAR2(512); 

    l_retval    PLS_INTEGER; 
    l_session    DBMS_LDAP.session; 

    l_wallet_loc  varchar2(256) := 'file:D:\wallets'; 
    l_wallet_pwd  varchar2(256) := 'pa55w0rd'; 
    l_wallet_ssl  number := 3; 

BEGIN 
    DBMS_LDAP.USE_EXCEPTION := TRUE; 
    l_dn := 'cn='||p_username||',ou=People,dc=internal,dc=net'; 

    BEGIN 
     l_session := DBMS_LDAP.init(l_ldap_host, l_ldap_port); 
    EXCEPTION 
     when others then 
     raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM); 
     RETURN 'exception1'; 
    END; 

    BEGIN 
     l_retval := DBMS_LDAP.open_ssl (l_session, l_wallet_loc, l_wallet_pwd, l_wallet_ssl); 
    EXCEPTION 
     when others then 
     raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM); 
     RETURN 'exception2'; 
    END; 

    BEGIN 
     l_retval := DBMS_LDAP.simple_bind_s(l_session, l_dn, p_password); 
    EXCEPTION 
    when others then 
    raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM); 
    RETURN 'exception3'; 
    END; 

    return 'pass'; 
END; 

そして、ここでは、私はそれを実行したときに何が起こるかです:

select ldap_auth('userID','userPassword') as results1 from dual 

ORA-20001:エラーが発生しました - -31202 -ERROR- ORA-31202:DBMS_LDAP:LDAPクライアント/ server error:ウォレットを開くことができません ORA-06512: "DBUSERNAME.LDAP_AUTH"、行33

この時点で私は立ち往生していますが、この作業を行う方法に関するオンラインの参考資料は見つかりません。

答えて

1

l_wallet_sslの宣言でnumberの代わりにpls_integerを使用できます。また、を削除して、open_sslファンクションコールでより有用なエラー(this linkのエラーの範囲については表4-86を参照)が得られるかどうかを確認することを検討してください。

1

IDKこの問題を解決するにはIDKを使用しますが、ここでは深い分析と同じ問題に関する多くのグーグルの回答に基づいています。私はADサーバーへのSSL接続のPL/SQL関数を作成しようとしていました。

1)私はあなたが述べた問題はこれで解決されるだろうと思って:あなたは自動にこれらの助成金を得るため

CREATE DIRECTORY mydir AS 'D:\wallets'; 

が、この場合、READとWRITEを付与する必要はありません。 しかし、この後に別の問題に直面するでしょう。それはあなたが11グラムのDBとMicrosoftのADサーバの最新バージョンを使用している場合、暗号は、Oracle DBで使用されるので、あなたはSSL接続を介してADに接続することができません

ORA-31202: DBMS_LDAP: LDAP client/server error: SSL handshake failed 

2)となります。これらはDBサーバーとADサーバーのバースに一致する必要がありますが、Oracleではセキュアな暗号ではなく古いIMHOが使用されています。 12cでlinkを部分的に修正しました

2)11gでこの問題を解決できた唯一の方法は、Javaによるものでした。 ソリューションはこれです:

SET SERVEROUTPUT ON; 
CALL dbms_java.set_output(1000); 

CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED LDAP AS 
import java.net.InetAddress; 
import java.net.UnknownHostException; 
import java.sql.*; 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.SQLException; 
import java.util.Arrays; 
import java.util.Hashtable; 
import java.util.List; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

import javax.naming.Context; 
import javax.naming.NamingException; 
import javax.naming.directory.DirContext; 
import javax.naming.directory.InitialDirContext; 

public class ldap { 
    public static boolean ldap_auth(String username, String password, String ldap_server, String application) throws SQLException, ClassNotFoundException, UnknownHostException{ 


     String keystore = "D:\\wallets"; 
     System.setProperty("javax.net.ssl.trustStore", keystore); 
     System.setProperty("javax.net.ssl.trustStorePassword", "password"); 

     Class.forName("oracle.jdbc.driver.OracleDriver"); 

     Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:SID", "USER", "password"); 

     Hashtable env = new Hashtable(11); 
     env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); 
     env.put(Context.PROVIDER_URL, ldap_server); 
     env.put(Context.SECURITY_PROTOCOL, "ssl"); 
     env.put(Context.SECURITY_AUTHENTICATION, "simple"); 
     env.put(Context.SECURITY_PRINCIPAL, username); 
     env.put(Context.SECURITY_CREDENTIALS, password); 

     InetAddress addr; 
     addr = InetAddress.getLocalHost(); 
     String ip = addr.getHostAddress(); 



     try { 
      DirContext ctx = new InitialDirContext(env); 

      System.out.println("Connection Successful!"); 
      ctx.close(); 

      return true; 
     } catch (Exception e) { 
      String errorMsg = e.toString(); 
      String[] errorCode = {"data 525", "data 773", "data 52e", "data 775", "data 701", "data 533", "data 532"}; 
      String returnErrorCode = null; 

      List<String> list = Arrays.asList(errorCode); 
      for(String word : list){ 
       if(errorMsg.contains(word)) { 
        returnErrorCode = word; 
       } 
      } 
      CallableStatement procin = conn.prepareCall("begin prc_log_action_java (:1,:2,:3,:4); end;"); 
      username = username.substring(0, username.indexOf('@')); 
      procin.setString(1, username); 
      procin.setString(2, returnErrorCode); 
      procin.setString(3, ip); 
      procin.setString(4, application); 
      procin.execute(); 
      procin.close(); 

      System.out.println(errorMsg); 
      return false; 
     } 

    } 
}; 

てみキャッチ部分は、私がキャッチし、無名ブロックを呼び出すと、テーブルの中に挿入するよADサーバによって生成されたエラーメッセージをログに記録するためのもので、私はあなたがこのコードを必要としないと思うが、ちょうどケースの場合。 errorCodeフィールドには、ADサーバーlink to AD error codesによって生成されたエラーコードの一部が表示されます。あなたはこのようにDBにPL/SQL関数を作成する必要があります。その後

:非常に重要である

create or replace function ldap_auth (p_username in varchar2, p_password in varchar2, p_ldap_server in varchar2)return boolean 
as language java 
name 'ldap.ldap_auth (java.lang.String, java.lang.String, java.lang.String, java.lang.String) return boolean'; 

最後はDB内のグラントpremissionsです。

call dbms_java.grant_permission('USER', 'SYS:java.net.SocketPermission', 'AD server:636', 'connect,resolve'); 
exec dbms_java.grant_permission('USER', 'SYS:java.util.PropertyPermission', 'javax.net.ssl.keyStore', 'write'); 
exec dbms_java.grant_permission('USER', 'SYS:java.util.PropertyPermission', 'javax.net.ssl.trustStorePassword', 'write'); 

commit; 
+0

これは私が解決策で期待していた以上のものです。今度はこのことを後で説明します。ありがとうございました! – kagaku

+0

さらにもう1つのことは、orapkiユーティリティ(例:https://docs.oracle.com/cd/E29542_01/core.1111/e10105/walletmgr.htm#ASADM10183)を使用してウォレットを正しく作成したことを願っています。 – n33l1x

関連する問題