Thursday 21 June 2012

Calling LDAP from PL/SQL

It seems to be a more frequent requirement to interact with LDAP directories from PL/SQL. Either populating records or reading them.

Here is a short test script to debug basic LDAP connection problems from Oracle PL/SQL. I have included some of the common error messages with a brief description below to help work out what is going wrong.


DECLARE
    v_retval pls_integer;
    v_session dbms_ldap.session;
BEGIN
    dbms_ldap.use_exception := TRUE;
    BEGIN
        v_session := dbms_ldap.init(
                  machine.example.com', -- LDAP hostname
                  389 ); -- ldap port
    EXCEPTION
    WHEN OTHERS THEN
        dbms_output.put_line(
            Error with dbms_ldap.init' ||
            SQLERRM ||'|'||
            SQLCODE);
    END;
    BEGIN
    -- bind with the dn of the user and password
        v_retval := dbms_ldap.simple_bind_s(
                v_session,
                cn=scott,dc=people,dc=example,dc=com',
                'tiger' ); -- password
        dbms_output.put_line('Connected ' || v_retval);
    EXCEPTION
        WHEN OTHERS THEN
            dbms_output.put_line(
                    'Error with simple_bind_s ' ||
                    'SQLERRM: ' || SQLERRM ||' | '||
                    'SQLCODE: ' || SQLCODE ||' | '||
                    'Return Value:' || v_retval);
    END;
    v_retval := dbms_ldap.unbind_s( v_session );
END;

This script can help discover a number of errors. Here are some of the most common.

ORA-24247: network access denied by access control list (ACL)
The call to dbms_ldap.init failed because the database access control list does not allow access to that destination.

So you can check what ACL exists for the database.
If you have access to the dba views you can use

SELECT host, lower_port, upper_port, acl
FROM dba_network_acls;


Or as the user trying to connect to LDAP run

SELECT host, lower_port, upper_port, privilege, status
FROM user_network_acl_privileges;

You may need to get the DBA to create a new ACL for the access to the LDAP directory. They can do this running as sys.
begin
    dbms_network_acl_admin.assign_acl (
        acl => 'acl.xml', -- the filename of the acl
        host => 'machine.example.com', -- LDAP server.
        lower_port => 389, -- LDAP port
        upper_port => 389); -- same LDAP port
end;
/
commit;

ORA-31204: DBMS_LDAP: PL/SQL - Invalid LDAP Session.
This will occur if you try to access a session that does not exist. From this test script if the dbms_ldap.init failed then there is no session when it tries to do the dbms_ldap.simple_bind_s. This error will occur when v_session does not have a valid value.

ORA-31202: DBMS_LDAP: LDAP client/server error: DSA is unwilling to perform. unauthenticated bind (DN with no password) disallowed
When user is passed but the password is blank and LDAP does not allow unauthenticated bind

ORA-31202: DBMS_LDAP: LDAP client/server error: Invalid credentials
Either the user DN or the password is not correct

ORA-31202: DBMS_LDAP: LDAP client/server error: Invalid DN syntax. invalid DN
The string used for the user DN is not a valid format.

Of course there are lots of other things to do with LDAP but this will give a few hints to get started and connected.

7 comments:

  1. hi,

    I m getting ORA-31204: DBMS_LDAP: PL/SQL - Invalid LDAP Session.

    what I need to do to solve this error.

    Please replay me ASAP.

    Regard's
    Nagesh

    ReplyDelete
    Replies
    1. Hi Nagesh

      This error usually occurs when the init fails and the variable you are holding the session identifier in does not have a valid value. So make sure you are using the same variable that was set from the init and that it is valid. Use the sample script above with your LDAP server details to see if the simple script works.

      Delete
  2. Hi Adrian,

    Thnx for quick reply.

    I tried above script ,it works fine.But when same code I used in function to authenticate and when I call that function by passing user_name and password it throws above mentioned error.

    I did'nt understand how to resolve that error.

    ReplyDelete
  3. It is a little difficult to work out what the issue might be. I think it might still be an authentication issue. Perhaps see if you can trap any authentication issues when you pass in the username and password.

    ReplyDelete
  4. Excellent! Thanks for the article. *****

    ReplyDelete
  5. Hi,
    In my case when i am executing my package with LDAP options, i am using ONE_WAY_AUTH type 2, and i am receive the :Error code : -31202
    Error Message : ORA-31202: DBMS_LDAP: Erro de cliente/servidor LDAP: SSL handshake failed
    Exception encountered .. exiting

    Have you seen this problem?
    Thank you

    ReplyDelete
    Replies
    1. Hi David

      Sorry for the slow reply.

      If it is SSL related you will need to set up Oracle Wallet and use dbms_ldap.open_ssl with the sslauth parameter set to 2 for one way auth before the call to bind.

      Adrian

      Delete