semi OT - Anonymous authentication against AD using DBMS_LDAP

  • From: Guillermo Alan Bort <cicciuxdba@xxxxxxxxx>
  • To: oracle-l-freelists <oracle-l@xxxxxxxxxxxxx>
  • Date: Wed, 11 Jan 2012 15:51:04 -0300

I am working on a pet project that aims to ease my job a lot, but it
requires getting information from Active Directory. Using my own DN (which
was easy enough to find out) I was able to log on to the AD and query just
about any information I wanted. However now I'm facing the problem of
authenticating the application using LDAP. The problem here is that the
sAMAccountName (which is what people usually use to log on to all the apps
as well as their laptops) is different from the CN in the DN. And as far as
my testing (and a few hours of google searches) I have to provide the DN in
order to authenticate.
I have tried setting the username and password fields to null in
dbms_ldap.simple_bind_s but it does not appear to work. The retval is 0 but
when I try to execute the dbms_ldap.search_s in order to get the DN based
on the sAMAccountName I get the following error:

ORA-31202: DBMS_LDAP: LDAP client/server error: Operations error. 000004DC:
LdapErr: DSID-0C0906DC, comment: In order to perform this operation a
successful bind must be completed on the connection., data 0, v1db0
ORA-06512: at "SYS.DBMS_SYS_ERROR", line 86
ORA-06512: at "SYS.DBMS_LDAP", line 1487
ORA-06512: at "SYS.DBMS_LDAP", line 234

Database version is 11.2.0.2

I am guessing the problem si that AD has anonymous authentication disabled,
but I'd like some confirmation. I am using code I got from ORACLE-BASE as
it's the easiest test I could find:


SET SERVEROUTPUT ON SIZE 1000000
DECLARE
  -- Adjust as necessary.
  l_ldap_host    VARCHAR2(256) := 'ad.company.com';
  l_ldap_port    VARCHAR2(256) := '389';
  l_ldap_base    VARCHAR2(256) := 'DC­,DC=company,DC=com';

  l_retval       PLS_INTEGER;
  l_session      DBMS_LDAP.session;
  l_attrs        DBMS_LDAP.string_collection;
  l_message      DBMS_LDAP.message;
  l_entry        DBMS_LDAP.message;
  l_attr_name    VARCHAR2(256);
  l_ber_element  DBMS_LDAP.ber_element;
  l_vals         DBMS_LDAP.string_collection;

BEGIN
  -- Choose to raise exceptions.
 DBMS_LDAP.USE_EXCEPTION := TRUE;
 l_retval := 1;
  dbms_output.put_line ('PRE Connected: ' || l_retval);
  -- Connect to the LDAP server.
  l_session := DBMS_LDAP.init(hostname => l_ldap_host,
                              portnum  => l_ldap_port);

   l_retval := DBMS_LDAP.simple_bind_s(ld     => l_session,
                                      dn     => NULL,
                                      passwd => NULL );

  dbms_output.put_line ('Connected: ' || l_retval);

  -- Get all attributes
  l_attrs(1) := 'distinguishedName'; -- retrieve all attributes
  l_retval := DBMS_LDAP.search_s(ld       => l_session,
                                 base     => l_ldap_base,
                                 scope    => DBMS_LDAP.SCOPE_SUBTREE,
                                 filter   => 'sAMAccountName=<somethings>',
                                 attrs    => l_attrs,
                                 attronly => 0,
                                 res      => l_message);

  IF DBMS_LDAP.count_entries(ld => l_session, msg => l_message) > 0 THEN
    -- Get all the entries returned by our search.
    l_entry := DBMS_LDAP.first_entry(ld  => l_session,
                                     msg => l_message);

    << entry_loop >>
    WHILE l_entry IS NOT NULL LOOP
      -- Get all the attributes for this entry.
      DBMS_OUTPUT.PUT_LINE('---------------------------------------');
      l_attr_name := DBMS_LDAP.first_attribute(ld        => l_session,
                                               ldapentry => l_entry,
                                               ber_elem  => l_ber_element);
      << attributes_loop >>
      WHILE l_attr_name IS NOT NULL LOOP
        -- Get all the values for this attribute.
        l_vals := DBMS_LDAP.get_values (ld        => l_session,
                                        ldapentry => l_entry,
                                        attr      => l_attr_name);
        << values_loop >>
        FOR i IN l_vals.FIRST .. l_vals.LAST LOOP
          DBMS_OUTPUT.PUT_LINE('ATTIBUTE_NAME: ' || l_attr_name || ' = ' ||
SUBSTR(l_vals(i),1,200));
        END LOOP values_loop;
        l_attr_name := DBMS_LDAP.next_attribute(ld        => l_session,
                                                ldapentry => l_entry,
                                                ber_elem  => l_ber_element);
      END LOOP attibutes_loop;
      l_entry := DBMS_LDAP.next_entry(ld  => l_session,
                                      msg => l_entry);
    END LOOP entry_loop;
  END IF;

  -- Disconnect from the LDAP server.
  l_retval := DBMS_LDAP.unbind_s(ld => l_session);
  DBMS_OUTPUT.PUT_LINE('L_RETVAL: ' || l_retval);
END;
/

I also tried using bind_s (instead of simple_bind_s)
   l_retval := DBMS_LDAP.bind_s(ld     => l_session,
                                      dn     => NULL,
                                      cred => NULL,
                                      meth => DBMS_LDAP.AUTH_SIMPLE );

but according to the documentation AUTH_SIMPLE is the only method supported
by the function ¬¬

Any help will be appreciated.

On another (side)note I am also thinking of using AD for APEX
authentication, but I'm facing the same issue of people using the
sAMAccountName instead of the DN, any ideas for this one?


Thank you very much
Alan.-

--
//www.freelists.org/webpage/oracle-l


Other related posts: