Title
Testing SSO authentication via PL/SQL (sso_auth.sql)

Date
2007-02-10

Summary
The PL/SQL block below helps troubleshoot SSO authentication. You will need the following values and update the script accordingly:
  • LDAP host
  • LDAP port
  • SSO server DN
  • Password of SSO server DN
  • User to be authenticated
  • Password

    Make sure to run the script as the orasso database user.

  • Details
    set serveroutput on size 30000
    set linesize 132
    -- Change the output file location here
    spool sso_auth_results.txt
    DECLARE
     ldap_host          VARCHAR2(256);
     ldap_port          PLS_INTEGER;
     sso_application    VARCHAR2(256);
     sso_passwd         VARCHAR2(256);
     ldap_base          VARCHAR2(256);
     use_ssl            VARCHAR2(1);
    
     retval             PLS_INTEGER;
     my_session         DBMS_LDAP.session;
    
     subscriber_handle  DBMS_LDAP_UTL.HANDLE;
     sub_type           PLS_INTEGER;
     subscriber_id      VARCHAR2(2000);
     subscriber_dn      VARCHAR2(2000);
    
     my_pset_coll       DBMS_LDAP_UTL.PROPERTY_SET_COLLECTION;
     my_property_names  DBMS_LDAP.STRING_COLLECTION;
     my_property_values DBMS_LDAP.STRING_COLLECTION;
     my_message         DBMS_LDAP.message;
    
     user_handle        DBMS_LDAP_UTL.HANDLE;
     user_id            VARCHAR2(2000);
     user_dn            VARCHAR2(2000);
     user_type          PLS_INTEGER;
     user_password      VARCHAR2(2000);
    
     group_handle       DBMS_LDAP_UTL.HANDLE;
     group_id           VARCHAR2(2000);
     group_type         PLS_INTEGER;
    
     user_search_base   VARCHAR2(2000);
     user_attr          VARCHAR2(2000);
    
     group_search_base  VARCHAR2(2000);
    
     my_mod_pset        DBMS_LDAP_UTL.MOD_PROPERTY_SET;
    
     my_attrs           DBMS_LDAP.STRING_COLLECTION;
     my_attr_value      VARCHAR2(2000);
     my_dn              VARCHAR2(256);
     my_entry           DBMS_LDAP.message;
    
     i  PLS_INTEGER;
     j  PLS_INTEGER;
     k  PLS_INTEGER;
    
     ------------------------------------------------
     -- Function : log_trace
     -- Description : Prints message logs onto the screen
     ----------------------------------------------------
     procedure log_trace(log_str IN VARCHAR2 DEFAULT NULL,
                         log_str_val IN VARCHAR2 DEFAULT NULL,
                         ind_level IN PLS_INTEGER DEFAULT 0)
     IS
      i PLS_INTEGER;
     BEGIN
    
      FOR i in 1..ind_level LOOP
        DBMS_OUTPUT.PUT('.   ');
      END LOOP;
    
      IF log_str_val IS NOT NULL THEN
        DBMS_OUTPUT.PUT_LINE(RPAD(log_str,30,' ') || ': ' ||
                             log_str_val);
      ELSIF log_str IS NOT NULL THEN
        DBMS_OUTPUT.PUT_LINE(log_str);
      ELSE
        DBMS_OUTPUT.PUT_LINE('--------------------------------------');
      END IF;
     END;
    
     --------------------------------------------------------------
     -- Function : sso_get_values
     -- Description : Retrieves the value for the given attribute
     --------------------------------------------------------------
     procedure sso_get_values(my_session IN DBMS_LDAP.SESSION,
                              my_message IN DBMS_LDAP.MESSAGE,
                              attr IN VARCHAR2,
                              value OUT VARCHAR2)
     IS
      my_entry     DBMS_LDAP.message;
      my_attr_name VARCHAR2(256);
      my_attrs     DBMS_LDAP.string_collection;
      my_ber_elmt  DBMS_LDAP.ber_element;
      my_vals      DBMS_LDAP.STRING_COLLECTION ;
    
     BEGIN
     -- get the first entry
       my_entry := DBMS_LDAP.first_entry(my_session, my_message);
       my_attr_name := DBMS_LDAP.first_attribute(my_session,
                                                 my_entry,
                                                 my_ber_elmt);
    
     -- Loop through each of the attributes one by one
       while my_attr_name IS NOT NULL loop
         my_vals := DBMS_LDAP.get_values (my_session,my_entry,
                                          my_attr_name);
         IF my_attr_name = attr THEN
           value := my_vals(my_vals.first);
           my_attr_name := NULL;
         ELSE
           my_attr_name := DBMS_LDAP.next_attribute(my_session,
                                                    my_entry,
                                                    my_ber_elmt);
         END IF;
       end loop;
    
      -- Free ber_element
       DBMS_LDAP.ber_free(my_ber_elmt, 0);
     END;
    
     BEGIN
       retval := -1;
    
     -- **************************************************************
     ------- PLEASE CUSTOMIZE THE FOLLOWING VARIABLES AS NEEDED ------
     -- **************************************************************
    
     ldap_host := '<host>';
     ldap_port := <port>;
     use_ssl := '<Y or N>';
    
     sso_application := '<SSO Server DN>';
     sso_passwd      := '<password of SSO Server DN>';
    
     -- Default subscriber.
     -- (else the sub_type and subscriber_id has to be changed accordingly.)
     sub_type      := DBMS_LDAP_UTL.TYPE_DEFAULT;
     subscriber_id := NULL;
    
     -- The user who needs to be authenticated.
    
     user_id := '<username>';
     user_password := '<password>';
    
     -- Nickname of user
     user_type := DBMS_LDAP_UTL.TYPE_NICKNAME;
    
     ------------ END OF CUSTOMIZATIONS ------------------------
    
     -- Choosing exceptions to be raised by DBMS_LDAP library.
     DBMS_LDAP.USE_EXCEPTION := TRUE;
    
     -----------------------------------------------
     -- Connect to the LDAP server
     -- and obtain and ld session.
     -----------------------------------------------
    
     log_trace();
     log_trace('Step : 1) - Binding to Directory ');
     log_trace();
     log_trace('Connecting to... ', ldap_host || ':' ||
               TO_CHAR(ldap_port),1);
    
     my_session := DBMS_LDAP.init(ldap_host,ldap_port);
    
     log_trace('Connection Successful...',NULL,1);
     log_trace('Ldap session ', RAWTOHEX(SUBSTR(my_session,1,8)) ||
               '(returned from ldap_init)',1);
    
     if use_ssl = 'Y' then
       retval := DBMS_LDAP.open_ssl(my_session, null, null, 1);
     end if;
    
     -- For debugging ..
     -- DBMS_LDAP.set_trace_level(65535);
    
     -----------------------------------------------
     -- Bind to the directory
     --
     -----------------------------------------------
    
     log_trace('Binding as... ', sso_application || '/' || sso_passwd,1);
    
     retval := DBMS_LDAP.simple_bind_s(my_session,
                                       sso_application,
                                       sso_passwd);
    
     log_trace('Bind successful...',NULL,1);
     log_trace('simple_bind_s Returns ',TO_CHAR(retval),1);
     log_trace('Binding to directory Successful ..',NULL,1);
    
     ---------------------------------------------------------------------
     -- Create Subscriber Handle
     --   for default subscriber.
     ---------------------------------------------------------------------
    
     log_trace();
     log_trace('Step : 2) - User Authentication');
     log_trace();
     log_trace('Creating default subscriber handle.. ', NULL, 1);
    
     retval := DBMS_LDAP_UTL.create_subscriber_handle(subscriber_handle,
                                                      sub_type,
                                                      subscriber_id);
    
     log_trace('create_subscriber_handle Returns ', TO_CHAR(retval),1);
    
     ---------------------------------------------------------------------
     -- Create User Handle
     --
     ---------------------------------------------------------------------
    
     log_trace('Creating user handle .. ', user_id, 1);
    
     retval := DBMS_LDAP_UTL.create_user_handle(user_handle,
                                                user_type,user_id);
    
     log_trace('create_user_handle Returns ', TO_CHAR(retval),1);
    
     ---------------------------------------------------------------------
     -- Set user handle properties
     --  (link subscriber to user )
     ---------------------------------------------------------------------
    
     log_trace('Configuring user handle .. ', 'subscriber handle',1);
    
     retval := DBMS_LDAP_UTL.set_user_handle_properties(user_handle,
                                         DBMS_LDAP_UTL.SUBSCRIBER_HANDLE,
                                         subscriber_handle);
    
     log_trace('set_user_handle_properties Returns ', TO_CHAR(retval),1);
    
     ---------------------------------------------------------------------
     -- Authenticate user and retrieve properties
     --
     ---------------------------------------------------------------------
    
     log_trace('Authenticating User .. ', 'user password:[' ||
               user_password || ']', 1);
    
     my_attrs(1) := 'orclguid';
     retval := DBMS_LDAP_UTL.get_user_props_and_auth(my_session,
                                                user_handle,
                                                DBMS_LDAP_UTL.AUTH_SIMPLE,
                                                my_attrs,
                                                user_password,
                                                NULL,
                                                my_pset_coll);
    
     log_trace('get_user_props_and_auth Returns ', TO_CHAR(retval),1);
    
     IF retval = DBMS_LDAP_UTL.SUCCESS THEN
       log_trace('*********** AUTHENTICATION SUCCESSFUL *************',
                 NULL,1);
     ELSE
       log_trace();
       log_trace(' Step 2) : ********** Authentication FAILED' ||
                 '(' || TO_CHAR(retval) || ')' || '!! ********** ',NULL,1);
       log_trace();
       log_trace();
       log_trace('####### DEBUGGING AUTHENTICATION PROCESS #######');
       log_trace();
    
       IF sub_type = DBMS_LDAP_UTL.TYPE_DEFAULT THEN
         log_trace();
         log_trace('Step 2.a) : Resolving Default subscriber');
         log_trace();
         log_trace('Searching for orcldefaultsubscriber attr',NULL,1);
         log_trace('in cn=Common,cn=Products,cn=OracleContext..',NULL,1);
         my_attrs.delete();
         my_attrs(1) := 'orcldefaultsubscriber';
         retval := DBMS_LDAP.search_s(my_session,
                                    'cn=Common,cn=Products,cn=OracleContext',
                                    DBMS_LDAP.SCOPE_BASE,
                                    'objectclass=*',
                                    my_attrs,
                                    0,
                                    my_message);
    
         log_trace('search_s Returns ', TO_CHAR(retval),1);
    
         IF retval <> DBMS_LDAP.SUCCESS THEN
           log_trace();
           log_trace('Unable to fetch orcldefaultsubscriber');
           log_trace('While resolving default subscriber');
           log_trace();
           sys.dbms_sys_error.raise_system_error(-31201,
                                  'Step 2.a) :Invalid Root Oracle Context');
         END IF;
    
         sso_get_values(my_session,my_message,'orcldefaultsubscriber',
                        my_attr_value);
         log_trace('Default Subscriber is .. ', my_attr_value,1);
         log_trace('(as configured in root orclcontext)',NULL,1);
         log_trace('Verifying existence of Default subscriber ..',NULL,1);
         subscriber_dn := my_attr_value;
         my_attrs.delete();
         my_attrs(1) := 'orclguid';
         retval := DBMS_LDAP.search_s(my_session,
                                      my_attr_value,
                                      DBMS_LDAP.SCOPE_BASE,
                                      'objectclass=*',
                                      my_attrs,
                                      0,
                                      my_message);
         log_trace('search_s Returns ', TO_CHAR(retval),1);
    
         IF retval <> DBMS_LDAP.SUCCESS THEN
           log_trace();
           log_trace('Default subscriber: ' || my_attr_value);
           log_trace('as configured in root oracle context doesnt exist ');
           log_trace();
           sys.dbms_sys_error.raise_system_error(-31201,
                                'Step 2.a) Invalid Root Oracle Context');
         END IF;
    
         log_trace('Retrieving Subscriber Oracle Context configurations ..',
                   NULL ,1);
         log_trace('(orclcommonusersearchbase,orclcommonusernickname and',
                   NULL,1);
         log_trace('orclcommongroupsearchbase)',NULL,1);
    
         my_attrs.delete();
         my_message := NULL;
         my_attrs(1) := 'orclcommonusersearchbase';
         my_attrs(2) := 'orclcommonnicknameattribute';
         my_attrs(3) := 'orclcommongroupsearchbase';
         retval := DBMS_LDAP.search_s(my_session,
                          'cn=Common, cn=Products, cn=OracleContext,'||
                          my_attr_value,
                          DBMS_LDAP.SCOPE_BASE,
                          'objectclass=*',
                          my_attrs,
                          0,
                          my_message);
    
         log_trace('search_s Returns ', TO_CHAR(retval),1);
    
         IF retval <> DBMS_LDAP.SUCCESS THEN
           log_trace();
           log_trace('Unable to retrieve Subscriber Oracle' ||
                     ' Context configurations' );
           log_trace();
           sys.dbms_sys_error.raise_system_error(-31201,
                                'Step 2.a): Invalid Subscriber Oracle Context');
         END IF;
    
         sso_get_values(my_session,my_message,'orclcommonnicknameattribute',
                        user_attr);
         sso_get_values(my_session,my_message,'orclcommonusersearchbase',
                        user_search_base);
         sso_get_values(my_session,my_message,'orclcommongroupsearchbase',
                        group_search_base);
         log_trace('orclcommonusernickname ',user_attr,1);
         log_trace('orclcommonusersearchbase ',user_search_base,1);
         log_trace('orclcommongroupsearchbase ',group_search_base,1);
    
         IF user_attr IS NULL THEN
           log_trace();
           log_trace('Unable to retrieve user nickname attribute ' );
           log_trace();
           sys.dbms_sys_error.raise_system_error(-31201,
                                'Step 2.a): Invalid Subscriber Oracle Context');
         END IF;
    
         IF user_search_base IS NULL THEN
           log_trace();
           log_trace('Unable to retrieve user search base attribute ' );
           log_trace();
           sys.dbms_sys_error.raise_system_error(-31201,
                                'Step 2.a): Invalid Subscriber Oracle Context');
         END IF;
    
         IF group_search_base IS NULL THEN
           log_trace();
           log_trace('Unable to retrieve group search base attribute ' );
           log_trace();
           sys.dbms_sys_error.raise_system_error(-31201,
                                'Step 2.a): Invalid Subscriber Oracle Context');
         END IF;
    
         log_trace('Subscriber Resolution successful..',NULL,1);
    
       ELSE
         log_trace();
         log_trace('Step 2.a) : Resolving subscriber: ' || subscriber_id);
         log_trace();
       END IF; -- Not a Default subscriber.
    
     -- Resolving User.
    
       log_trace();
       log_trace('Step 2.b) : Resolving User ');
       log_trace();
       log_trace('User details: ',NULL,1);
       log_trace('user nickname ',user_id,1);
       log_trace('user nickname attribute ',user_attr,1);
       log_trace('user search base ',user_search_base,1);
       log_trace('Searching for user ..',NULL,1);
       my_attrs.delete();
       my_attrs(1) := 'orclguid';
       retval := DBMS_LDAP.search_s(my_session,
                                    user_search_base,
                                    DBMS_LDAP.SCOPE_SUBTREE,
                                    user_attr || '=' || user_id,
                                    my_attrs,
                                    0,
                                    my_message);
    
       log_trace('search_s Returns ', TO_CHAR(retval),1);
       IF retval <> DBMS_LDAP.SUCCESS THEN
         log_trace();
         log_trace('Unable to find user');
         log_trace();
         sys.dbms_sys_error.raise_system_error(-31201,
                              'Step 2.b) :User doesnt exist ');
       END IF;
    
     -- count the number of entries returned
       retval := DBMS_LDAP.count_entries(my_session,my_message);
       log_trace('Number of users found :  ',TO_CHAR(retval),1);
    
       IF retval < 1 THEN
         log_trace();
         log_trace('Unable to find user');
         log_trace();
         sys.dbms_sys_error.raise_system_error(-31201,
                              'Step 2.b) :User doesnt exist ');
       END IF;
    
       IF retval > 1 THEN
         log_trace();
         log_trace('Multiple users found');
         log_trace();
         sys.dbms_sys_error.raise_system_error(-31201,
                              'Step 2.b) :Multiple users found' ||
                              ' for the given criteria ');
       END IF;
    
       my_entry := DBMS_LDAP.first_entry(my_session,my_message);
       my_dn := DBMS_LDAP.get_dn(my_session, my_entry);
       log_trace('User DN : ',my_dn,1);
       log_trace('User Resolution Successful ..',NULL,1);
       user_dn := my_dn;
    
     -- Authenticating user
    
       log_trace();
       log_trace('Step 2.c) : Authenticating User');
       log_trace();
       log_trace('Subscriber details: ',NULL,1);
       log_trace('Subscriber DN is ',subscriber_dn,1);
       log_trace('User details: ',NULL,1);
       log_trace('User DN is ',user_dn,1);
       log_trace('User Password is ',user_password,1);
       log_trace('Performing ldap compare ..',NULL,1);
    
       retval := DBMS_LDAP.compare_s (my_session,
                                      user_dn,
                                      'userpassword',
                                      user_password);
    
       log_trace('compare_s Returns ', TO_CHAR(retval),1);
    
       IF retval <> DBMS_LDAP.SUCCESS THEN
         log_trace();
         log_trace('ldap compare failed',NULL,1);
         log_trace();
         sys.dbms_sys_error.raise_system_error(-31201,
                              'Step 2.c) :ldap compare failed/' ||
                              ' authentication failed ');
       END IF;
    
       log_trace('Authentication successful ..',NULL,1);
    
     END IF; -- Authentication not successful.
    
     -- unbind from the directory
    
     log_trace();
     log_trace('Step : END) - End LDAP Session ');
     log_trace();
     log_trace('Unbinding from directory...',NULL,1);
     retval := DBMS_LDAP.unbind_s(my_session);
     log_trace('unbind_res Returns ', TO_CHAR(retval),1);
    
     -- Handle Exceptions
    
     EXCEPTION
      WHEN OTHERS THEN
       log_trace();
       DBMS_OUTPUT.PUT_LINE(' ***** EXCEPTION ENCOUNTERED ********* ');
       DBMS_OUTPUT.PUT_LINE(' Error code    : ' || TO_CHAR(SQLCODE));
       DBMS_OUTPUT.PUT_LINE(' Error Message : ' || SQLERRM);
       log_trace();
    
     END;
    /
    spool off
    

    Applicable Versions
    Oracle Single Sign-On 9i
    Ahmed Aboulnaga

    .com .com