1 Reply Latest reply: Feb 26, 2013 4:40 AM by 949766 RSS

    Why are Java SASLFactories missing when called via PL/SQL but not from JRE?

    949766
      Hi

      This may be quite a technical point about SASL and JCE Providers etc OR it may just be a question about how Oracle PL/SQL interfaces with Java.

      The background is that I am trying to get a Java opensource library to run in Oracle DB - this is for specialized communication from Database to other servers.

      The library uses a SASL mechanism to authenticate with the server and this (appears) to rely on JCE Providers installed and provided by the JRE.

      I have some Java code working which uses the library - this runs OK in NetBeans/Windows environment and also using Linux/Oracle JRE directly such as:

        +# $ORACLE_HOME/jdk/bin/java -classpath "./MyMain.jar:./OtherSupport.jar" package.TestClient+

      However it refuses to work (throws a NullPointerException) when called from PL/SQL.

        +FUNCTION send_a_message (iHost IN VARCHAR2,+
           iPort IN NUMBER,
          +iLogin IN VARCHAR2,+
          +iPasswd IN VARCHAR2,+
           iRecipient IN VARCHAR2,
           iMessage IN VARCHAR2) RETURN NUMBER
         AS LANGUAGE JAVA
         NAME package.TestClient.sendATextMessage(java.lang.String, int, java.lang.String, java.lang.String, java.lang.String, java.lang.String) return int';

      In the Java code this is:

         public static int sendATextMessage(String iHost,
           int iPort,
           String iLogin,
           String iPasswd
           String iRecipient,
           String iMessage)

      I've tracked the issue down to there being no SaslClientFactories (via Sasl.getSaslClientFactories()) showing when called from PL/SQL whereas 3 are available when run from within Java directly. This via:

         Enumeration<SaslClientFactory> facts = Sasl.getSaslClientFactories();
         System.out.println("Found Sasl Factories [" & (facts != null)  & "] size[" & Collections.list(facts).size() & "]");


      So, is there some aspect of Java initialisation that I'm missing when calling from PL/SQL (which means SASL factories aren't getting loaded into JRE) or is there something different in SASL setup?

      Any pointers appreciated.

      Thanks
      Dave
        • 1. Re: Why are Java SASLFactories missing when called via PL/SQL but not from JRE?
          949766
          Ok, after a bit of reading and general hacking about I have got this working.

          What I hadn't initially understood/remembered is that for a Stored Procedure the JVM installed on file system with Oracle isn't actually used - java code is loaded into the database and hence a different set of base functions are available. The following is a good explanation of this http://docs.oracle.com/cd/B14117_01/java.101/b12021/appover.htm#BGBIBDAJ

          So "out of the box" the Oracle Database appears to come loaded with only two of the Sun security providers i.e. no com.sum.security.SASL

          >
          OBJECT_NAME             OBJECT_TYPE     STATUS   TIMESTAMP
          -------------------        -------    -------------------
          com/sun/security/auth/NTSid  JAVA CLASS    VALID   2013-02-14:14:08:57
          com/sun/security/jgss/GSSUtil    JAVA CLASS    VALID   2013-02-14:14:08:57
          >



          This is from:
          >
          SELECT
            object_name,
            object_type,
            status,
            timestamp
          FROM
            user_objects
          WHERE
            (object_name NOT LIKE 'SYS_%' AND
             object_name NOT LIKE 'CREATE$%' AND
             object_name NOT LIKE 'JAVA$%' AND
             object_name NOT LIKE 'LOADLOB%') AND
             object_type LIKE 'JAVA %' AND
             object_name LIKE 'com/sun/security%'
          ORDER BY
            object_type,
            object_name;
          >


          My solution (which may well be a work-around) is the following:

          1) Downloaded JDK Source and extracted "com.sun.security.sasl" java code to my project

          2) Added following code to my Stored Procedure ()

          >
          Enumeration<SaslClientFactory> saslFacts = Sasl.getSaslClientFactories();
          if (!saslFacts.hasMoreElements()) {
            System.out.println("Sasl Provider not pre-loaded");
            int added = Security.addProvider(new com.sun.security.sasl.Provider());
            if (added == -1) {
              System.out.println("Sasl Provider could not be loaded");
              System.exit(added);
            }
            else {
              System.out.println("Sasl Provider added");
            }
          }
          >

          3) Built my JAR file with the sasl package embedded (note: could only find Java 6 code, so had to comment out some GSS lines - but wasn't intending to use these)

          4) Loaded JAR to oracle via "loadjava".

          5) Add permissions (only found this out after a couple of failed runs)

          >
          call dbms_java.grant_permission('XMPP', 'SYS:java.security.SecurityPermission', 'putProviderProperty.SunSASL', '' );
          call dbms_java.grant_permission('XMPP', 'SYS:java.security.SecurityPermission', 'insertProvider.SunSASL', '' );
          >

          6) Run gives the following:

          >
          Sasl Provider not pre-loaded
          Sasl Provider added
          ...etc...
          >

          It works!. I confess I'm not sure of the implications of this for multiple calls/performance and if it will need to be added for each stored procedure call - may post back.

          For completeness I should point out that after my load the Security providers look like this:

          >
          OBJECT_NAME             OBJECT_TYPE     STATUS   TIMESTAMP
          -------------------        -------    -------------------
          com/sun/security/auth/NTSid    JAVA CLASS    INVALID  2013-02-15:09:11:36
          com/sun/security/jgss/GSSUtil    JAVA CLASS    INVALID  2013-02-15:09:11:37
          com/sun/security/sasl/Provider    JAVA CLASS    VALID    2013-02-15:10:03:21
          >

          i.e. the original couple are "INVALID" !


          Dave


          Edited by: 946763 on Feb 26, 2013 2:35 AM