Novell is now a part of Micro Focus

SecretStore Single Sign-on

Articles and Tips: article

CAMERON MASHAYEKHI
Network Security Development
Product Group

01 Nov 1999


Explains the rationale behind Novell's SecretStore and Single Sign-on. Discusses SecretStore architecture. Contains sample code.

Introduction

As a foundation to most security software solutions, there has always been a need for a secure storage of sensitive data. The inherent function of this kind of storage is to protect the confidentiality and integrity of the data stored in it against unwanted modification and disclosure for a later use of the security system. Consequently, the methods of access, storage, and retrieval of the sensitive data should also protect the confidentiality and integrity of it. Since networks have become an integral part of the computing environment, access, storage, and retrieval of data from secure storage in a secure manner from any point on the network is a must, and it is a complex problem to solve.

SecretStore Service (SSS) is an NDS based solution to this problem. It is designed to provide a foundation for the security applications and subsystems on the network. Access to this storage is governed by authentication to NDS and having a valid identity and set of credentials known to NDS. The clearance granted to the user trying to access the SecretStore is controlled by Discretionary and Mandatory Access Controls in NDS. One of the first applications of the SecretStore is Single Sign-on (SSO.)

Rationale behind Single Sign-on

Due to the distributed nature of the client-server applications, there is a need for authenticating clients of these applications before granting them access to their services and resources. Even though these applications are running on the network, they ignore the fact that a user must have authenticated to the network before accessing the target application. Therefore, these applications ignore that the user must have an identity and a set of credentials on the network.

The reason network applications are ignoring the client's credentials is that these applications have not been Directory Enabled. In order to enable the applications to take advantage of the security features of the Directory, there has been a need for making the authentication interfaces available to the server and client components of the network applications. The last step in this process is to standardize Directory interfaces to solve the problem of accessing Directories provided by multiple vendors.

Ultimately, in an ideal situation in the future, all users will have a unified identity across all of the networks and the applications will all be Directory enabled. As a result, users will only log in once to the network, and all applications across the intranet and internet will be able to use their unified identities and credentials to grant clients access to their services. However, between now and then a solution is needed to manage the multiple identities of each user and provide their credentials to the network applications for authentication to give the illusion of having a single identity and a single set of credentials.

Novell Single Sign-on is our SecretStore and NDS based solution to this problem. In its current form, Novell SSO provides this solution in the Novell intranets. At a higher level, in the internet space, Novell's DigitalMe will provide the same solution for internet community of the users. Both SSO and DigitalMe are services that need to use SecretStore to store client's multiple identities, secrets, and credentials needed to authenticate them to their target applications.

Novell Single Sign-on is the first application of the SecretStore. SecretStore is also employed in Novell's PKIS and other security subsystems.

The illustrations (fig.1, fig.2, and fig.3) demonstrate the user's authentication process to a network application, and how Novell SSO enabled applications can interface with the SecretStore to authenticate the user.

SSO Operation

Figure 1: Application's successful authentication before SSO enabling.

Figure 2: First time successful authentication to an enabled application.

Figure 3: Subsequent user authentication to the application.

As it is shown in Fig. 3, the interaction of the authentication module with the user has been eliminated and is replaced with the interaction of that subsystem with the SecretStore to provide SSO. It should be intuitively clear that in order for all of this to succeed, a user must be logged in and authenticated to NDS before accessing SecretStore.

SecretStore Architecture

SecretStore implementation in NDS is based on a hidden set of attributes. Inherently, hidden attributes in NDS are not accessible from the client through normal means such as administrative utilities or DSAPIs. The only way to access SecretStore is through the use of SecretStore APIs. These APIs in version 1.0 are based on SecretStore NCP 92 and its subverbs. NCP 92 is a self contained, stand alone protocol that is not based on NDS NCPs. This NCP and SecretStore APIs are unique in the sense that they have the ability to create an encrypted tunnel between client and server to protect the confidentiality and integrity of the data in transmission. SecretStore operations between client and server, unlike NDS APIs, do not have iterations, and no states are kept in between the operations. Each API call sets a session between the client and server for one request and one response and negotiates the key sizes and encryption algorithm between the two if necessary. At the end of the API call, upon receiving the response from NDS, the session information is destroyed, and the same process will be repeated for the next API operation.

In an NDS tree that has the SecretStore Service installed, each user that tries the service with an enabled application will have a SecretStore created on its User Object. SecretStore is a per user object. Based on its architecture and protocols, SecretStore is only readable by the owner. However, an NDS entity with sufficient administrative rights can manipulate the users' SecretStores. This will allow creation, modification, and removal of users' SecretStores by the administrator. However, successful reading of the secrets can only be done by the owner of the secrets in the SecretStore.

Deployment

For discussions on deploying the SecretStore on your network, refer to the Novell Research Web site at www.novell.com/researchfor current Developer Note and AppNote articles. There is also useful information in the "readme" files on the SSO installation CD.

Enabling Applications

There are several ways of enabling the client components of the applications that are listed below. These methods depend on the type of applications, the availability of source application, or extensibility of interfaces provided by the manufacturer of the software.

  1. Having access to the source of the client applications. This is the easiest way for enabling applications.

  2. Having extensible interfaces where you are able to add extensions to connect the application authentication to SecretStore for SSO. Lotus Notes and Entrust Entelligence are examples of these kinds of applications.

  3. Writing SSO enabled application launchers that can feed secrets through command line parameters to the applications.

  4. Creating screen scraping application launchers that can Read from and Write to SecretStore to SSO enable applications.

  5. Having applications that have a replaceable authentication module that can be replaced with an SSO enabled version of the module. An example of this kind of applications is PeopleSoft.

  6. Use applications that have input/output streams that can be intercepted for capturing and feeding secrets to SecretStore to be used during authentication process. An example is capturing authentication related fields in XML forms on Web based applications to interface with SecretStore.

Commonly, those developers that are enabling application code should find and modify the following points in the application's client code:

  1. Point of Begin User Authentication code. At this point, the SSO interface code for Read to SecretStore should be inserted.

    Success: The application secret is retrieved from SecretStore and is passed to the application.

    Note: Failure of the authentication using the secret that was read out of SecretStore in this stage would mean that the secret in SecretStore did not match the application secret. At this point, step 2 should be signaled to update the SecretStore with the correct secret.

    Failure: Step 2 should be signaled to populate the SecretStore after the successful authentication.

  2. Point of End User Authentication code. At this point, the SSO interface code for Add and Write should be added to the application if the authentication was performed successfully through the interaction with the user. If the signal from step 1 was for update, only a Write of the verified secret is needed to refresh the SecretStore.

  3. Point of Forced Periodic Credential Change Code. A periodic forced change of the password should update the user secret with a Write to the SecretStore.

  4. Point of Manual Credential Change Code. The user's manual password change should update the user secret with a Write to SecretStore.

Novell's Convention for Secret IDs

To prevent name collisions, Novell has devised a naming convention for defining Secret IDs. Conforming names can be registered with Novell through DeveloperNet for the best result. Conforming names should have the following format:

\\DNS Name\Software Name: Optional information

for example:

\\Novell.com\SSO Sample App: Version 1.0

As defined by the SecretStore architecture, these IDs can be 256 characters long (including the null character).

Support of Multiple Secret IDs for the Same User in the Same Application

Support for multiple application user IDs for the same NDS client can be achieved through concatenation of those IDs to the end of the secret ID. This way the same application can have unique secrets per user IDs for the same NDS client.

In the example below, a client of NDS has two different user IDs for his/her GroupWise accounts.

\\Novell.com\GroupWise: Version 5.5\JDoe \\Novell.com\GroupWise: Version 5.5\Admin

or

\\Novell.com\GroupWise: Version 5.5\Prv-mail6\JDoe \\Novell.com\GroupWise: Version 5.5\Prv-mail9\JDoe

Enhanced Protection

In the current NDS authentication scheme with passwords, it is possible for the administrator of the NDS to launch the following attack on the SecretStore. The administrator can change the user's NDS password through the available administrative means, log in as the user with the new password, and attempt to read the secrets in the user's SecretStore. To prevent this attack, SecretStore Write API has an optional flag for Enhanced Protection that turns the non-repudiation feature on for that target secret. Once a secret is flagged with EP feature, it will be locked if the user's NDS password was changed by the administrator. Periodic password changes by the user does not result in EP flagged secrets getting locked. Once the SecretStore gets locked, the Unlock API should be used to unlock the SecretStore. This API requires the user to supply the last valid NDS password in order to unlock the SecretStore. If the Admin changes the password multiple times, the last valid user password will still be the key to unlock the SecretStore, not the last password entered by the Admin. If the administrative password change is due to the user forgetting his/her NDS password, the locked secrets will be useless and the user should remove them all in order to release the lock on the SecretStore. The latter situation is the motivation behind making the EP an optional feature. It is highly recommended that the sensitive secrets be flagged with EP, so in case the user forgets the NDS password, all the secrets in the user's SecretStore will not be lost.

Management APIs

Enumerate, RemoveSecretStore, and RemoveSecret are management APIs. These APIs can be used to perform management functions. For example, a combination of management functions and enabling functions were used to create the ConsoleOne Snap-in for managing the SecretStore. Since this utility can be used by the user, as well as the Administrator, the long form of the APIs was used to create a set of Java wrapper functions to provide the APIs in Java for ConsoleOne consumption (sso.jar.)

Enumerate API lists all the SecretIDs in the user's SecretStore. Since all of the SecretStore APIs are one time calls with no iteration, the caller should allocate a big enough buffer to return the user secrets. Maximum buffer size is regulated by the NCP restrictions and can be as big as 64k. These SecretIDs will be returned in the SecretIDList buffer and are "*" separated. Calling code can parse the buffer using the "*" as a delimiter token. As a result, "*" is the only reserved character with a special meaning for SecretStore. If the buffer is small, SecretStore returns as many SecretIDs as it can in the buffer, with the appropriate error code.

This API has the regular expression parsing capability. If you define a search string, you will be able to limit the scope of SecretIDs that will be returned. For example, "GW*" search string will cause the SecretStore to return every SecretID that starts with the letters "GW". Consequently, a NULL or "*" search string will act as no search string and SecretStore will return all of the secrets.

RemoveSecretStore API causes the SecretStore to be removed from the target user object in NDS. This API should be used strictly for management purposes and with care.

RemoveSecret API provides the means for removing a single secret from a user's SecretStore. If this secret were the last on in that target SecretStore, it would cause the service to remove the SecretStore all together.

Management Through ConsoleOne

Installation of the SSO Snap-in in the ConsoleOne version 1.2 or better will enable this utility to provide the means for the Administrator or the user to manage SecretStore. ConsoleOne provides the functionality to view a list of SecretIDs in the SecretStore. The user can create new secrets, remove old secrets, modify existing secrets, and view secrets. As the functionality of read API was explained, it only allows the owner to view secrets. This would mean that in this utility the Administrator can perform all of the functions listed above except for viewing user secerts.

Since with SSO it is possible that users would not be using their passwords for long periods of time, the view option in ConsoleOne will be extremely handy. A user can use this feature to look up secrets and to remember them if there was a need to use the applications in the absence of NDS. For example, users going on trips, trying to use enabled applications on laptops, can lookup the old passwords in their SecretStores to refresh their memories.

Sample Code

The following code excerpts are from a hypothetical application. LaunchPassowrdDlg function is the code that calls authentication sub-functions.

int LaunchPasswordDlg(void)

{

        AfxSetResourceHandle (theApp.m_hInstance); 

        CSSOTutorDlg  dlg;

        return (dlg.DoModal ());

}

CSSOTutorDlg class is the code that puts up the dialogs for user name and password and verifies the correct password.

void CSSOTutorDlg::OnOK() 

{

        // Declare an instance of the Authenticated Dialog

        CAuthDlg dlgAuth;

        // Declare an instance of the Not Authenticated Dialog

        CNotAuthDlg      dlgNotAuth;        



        // Declare a new string variable to hold the returned password

        CString sPassword;



        // Return the content of the password field to it's variable

        UpdateData(TRUE);



        // Transfer the password the sPassword variable for comparison

        sPassword = m_strPassword;



        if (sPassword == "killerapp")

            // Show the successful authentication dialog

            dlgAuth.DoModal();

        else

            // Show the not authenticated dialog

            dlgNotAuth.DoModal();



        CDialog::OnOK();

}

To enable this application an engineer will have to locate these functions; this is where the person will go to SSO enable the code.

The following shows the same functions after they have been enabled.

/* ========================

     * SecretStore header files 

 * =======================

 */

#include "nwss.h"

#include "splash.h"



#define APP_ID "\\\\novell.com\\SSO Tutor Application:Version 1.0"



int LaunchPasswordDlg(void)

{



    AfxSetResourceHandle (theApp.m_hInstance); 



    //***********************************************

    //* Check for the existence of the SecretStore

    //***********************************************



        int              doAuthenticate = FALSE, rcode;

        SS_SECRET_T             appSecret;

        SS_SECRET_ID_T              secretID;

        char                secret[128];



        /* BEGIN C Code HERE 

         * =================

         */

        /* initialize the data structures */

        appSecret.data = secret;



        /* define the secret name */

        strcpy(secretID.id, APP_ID);



        /* calculate the secret name's length */

        secretID.len = strlen(APP_ID) + 1;



        /* get the lenght of the secret buffer */

        appSecret.len = sizeof(secret);



        /* now call the SecretStore with the short form of the Read API */

        if (NWSS_ReadSecret(&secretID, (SS_SECRET_T *)&appSecret, NULL))&
        {

            /* in case of error continue */

            doAuthenticate = TRUE;

        }

        else

        {

            /* in case of success verify the secret */

            if(strcmp(appSecret.data, "killerapp"))

            {

                /* if the secret is out of sync then we need to update

                        SecrStore

                */

                    doAuthenticate = TRUE;

                    /* remove the outdated password */

                        rcode = NWSS_RemoveSecretID(&secretID);&
                    /* instead of removing an application can update SecretStore

                        with a write to

                    */

                }

                else

                {

                    /* secret matched (success)*/

                    /* display Novell SSO splash screen */

                        CSplashWnd splash(IDB_NOVSSO, NULL, NULL);



                        splash.ShowWindow (SW_SHOW);



                    /* display 2 seconds */

                        Sleep (2000);

                        splash.SendMessage(WM_CLOSE, 0, 0);  // clear the splash screen

                }

            }



    

    /* END C CODE HERE 

     * ===============

     */

/* if the authenticate flag was set then perform authentication */

    if (doAuthenticate)

    {

        CSSOTutorDlg  dlg;

        return (dlg.DoModal ());

    }



        return 0;

    }

If in the function above the authentication class was called, it would mean that either it is the first time that the application is trying to populate the SecretStore, or the secret in NDS is out of sync with the application.

void CSSOTutorDlg::OnOK() 

    {

        //***********************************************

        //* Check for the existence of the SecretStore

        //***********************************************



        int             doPopulate = FALSE;

        int             rcode = NWSS_SUCCESS;

        SS_SECRET_T         appSecret;

        SS_SECRET_ID_T              secretID;

        char                secret[128];



        // Declare an instance of the Authenticated Dialog

        CAuthDlg dlgAuth;



        // Declare an instance of the Not Authenticated Dialog

        CNotAuthDlg     dlgNotAuth;     

    

        // Declare a new string variable to hold the returned password

        CString sPassword;

    

        // Return the content of the password field to it's variable

        UpdateData(TRUE);



        // Transfer the password the sPassword variable for comparison

        sPassword = m_strPassword;



        if (sPassword == "killerapp")

        {

            // Show the Authenticated dialog

            dlgAuth.DoModal();

            doPopulate = TRUE;

        }

        else

            // Show the Not Authenticated dialog

            dlgNotAuth.DoModal();

    

        CDialog::OnOK();



    /* BEGIN C Code HERE 

     * =================

     */

/* now that the authentication was successful and the 

    populate flag was set we update the SecretStore

*/

        if(doPopulate)

        {

            /* initialize the data structures */

            appSecret.data = secret;

                        

            /* define a secret name */

            strcpy(secretID.id, APP_ID);



            /* calculate the secret name's length */

            secretID.len = strlen(APP_ID) + 1;



            /* get the lenght of the secret buffer */

            appSecret.len = sizeof(secret);



            /* now call the SecretStore using the short form of the read API */

            if (rcode = NWSS_ReadSecret(&secretID, &
                    (SS_SECRET_T *)&appSecret, NULL))&
            {

                /* initialize or populate the SecretStore */

                if (rcode = NWSS_ERR_STORE_NOT_FOUND)

                {

                    rcode = NWSS_AddSecretID(&secretID);&
                    strcpy(appSecret.data, "killerapp");

                    rcode = NWSS_WriteSecret(&secretID, &appSecret);&
                }

            }

        }

    /* END C CODE HERE 

     * ===============

     */

    }

Code samples and documentation for SecretStore is available through http://developer.novell.com/ndk. SSO client components are freely available through Novell's DeveloperNet. In addition to these components, there are downloadable code samples and documentation on this Web site.

* Originally published in Novell AppNotes


Disclaimer

The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.

© Copyright Micro Focus or one of its affiliates