Implement the Authentication Interface

Contents
casso1283
Creating the custom authentication scheme includes implementing the following procedures:
  • A query procedure
  • An initialization procedure
  • A user authentication procedure
  • A release procedure

Query Procedure

When the custom authentication scheme loads into memory,
SiteMinder
calls the query procedure to garnish the following pieces of information:
  • The version and description of the authentication scheme.
  • The kind of credentials that are required for user authentication.
  • (Optional) A URL that specifies where to retrieve this information.
The query function reads a constant value that specifies what information the authentication scheme requires. The function passes back the appropriate information in the designated output parameter. When the call to the query function completes successfully,
SiteMinder
has the appropriate information about the authentication scheme.
Example: Query Procedure
/*
// SmAuthQuery:
// SiteMinder calls this function to request scheme information.
// The function returns a description of the scheme, or credentials that are
// required for the authentication.
//
// PARAMETERS:
// [in] lpszParam:        Parameter string specified in the authentication scheme.
// [in] lpszSharedSecret: Shared secret string specified in the authentication scheme.
// [in] Sm_AuthApi_QueryCode_t: Request code is any one of the following
//      1. Sm_AuthApi_QueryDescription    - Request description of the scheme.
//      2. Sm_AuthApi_QueryCredentialsReq - Request the credentials required by the
//                                          scheme and where to obtain them.
// [out] lpszStatusBuffer: Buffer for a character string response.
// [out] lpnStatusCode:  Buffer for a numeric response.
//
// RETURNS:
// Any one of the following  Sm_AuthApi_Status_t values:
//   Sm_AuthApi_Success
//   Sm_AuthApi_Failure
*/
Sm_AuthApi_Status_t SM_EXTERN SmAuthQuery (
    const char*   lpszParam,                    /* parameter (null-terminated) */
    const char*   lpszSharedSecret,             /* shared secret (null-terminated) */
    const         Sm_AuthApi_QueryCode_t nCode, /* query code */
    char*         lpszStatusBuffer,             /* status buffer to hold the null-terminated string */
    int*          lpnStatusCode)                /* status code */
{
    strcpy (lpszStatusBuffer, "");
    switch (nCode)
    {
        case Sm_AuthApi_QueryDescription:
            strcpy (lpszStatusBuffer, SCHEME_DESCRIPTION);
            *lpnStatusCode = SCHEME_VERSION;
            break;
        case Sm_AuthApi_QueryCredentialsReq:
            *lpnStatusCode = Sm_AuthApi_Cred_Basic;
            break;
        default:
            return Sm_AuthApi_Failure;
    }
    return Sm_AuthApi_Success;
}

Initialization Procedure

To initialize your custom authentication scheme, implement the SmAuthInit() function. The calling sequence specifies two input parameters. You can use one or both of these parameters as best suits your implementation.
Example: Initialization Procedure
C++
// SmAuthInit:
// PARAMETERS:
// [in] lpszServerParam:  Parameter string as specified for the authentication scheme.
// [in] lpszSharedSecret: Shared secret string specified in the authentication scheme.
//
// RETURNS:
// Any one of the following Sm_AuthApi_Status_t values:
//   Sm_AuthApi_Success
//   Sm_Authapi_Failure (scheme will not be loaded)
*/
Sm_AuthApi_Status_t SM_EXTERN SmAuthInit (
    const char * lpszServerParam,       /* server parameter */
    const char * lpszSharedSecret)      /* server shared secret */
{
  return Sm_AuthApi_Success;
}

User Authentication Procedure

The authentication process includes the following steps:
  1. User login
    . The user supplies a login ID (such as jsmith) for authentication purposes.
  2. Disambiguation phase
    . User disambiguation is the process of locating a user in the user store, such as an LDAP user directory or an ODBC database. Either
    SiteMinder
    or the custom authentication scheme can look up the user in the user store.
    Before the lookup operation can begin, a complete DN or a search expression must be constructed based upon the supplied login ID. For example, if the login ID is jsmith, the DN used to search the user store might be constructed as follows:
    uid=jsmith,ou=marketing,o=myorg.org
    An LDAP search expression can also be used to search an LDAP user directory, and a SQL query is used to search an ODBC database—for example:
    (&(objectclass=inetOrgPerson)(uid=jsmith))
    select Name from SmUser where Name = '
    jsmith
    '
    Multiple results are possible, given that the LDAP DN or the ID stored in the ODBC database might apply to different users who have different passwords.
  3. Authentication phase
    . The custom authentication scheme compares the known credentials of each disambiguated user with the credentials supplied during login—for example, by comparing the hash of the supplied password against the hash in the user store.
SiteMinder
calls SmAuthenticate() at the beginning of the user disambiguation phase. Either
SiteMinder
or the custom authentication scheme can disambiguate the user. The authentication scheme indicates whether it has performed the disambiguation through one of the following return codes:
  • Sm_AuthApi_NoUserContext
    The authentication scheme asks
    SiteMinder
    to disambiguate the user.
    When this code is returned, the authentication scheme leaves the parameter lpszUserMsg empty.
    SiteMinder
    gets the login ID from the Agent, constructs the DN or search expression based on the login ID and the information defined in the
    SiteMinder
    User Directory Properties dialog box, and disambiguates the user by looking up the user in the user store.
  • Sm_AuthApi_Success
    The authentication scheme asks
    SiteMinder
    to disambiguate the user.
    The authentication scheme puts the login ID into lpszUserMsg.
    SiteMinder
    uses that value to construct the DN or search expression and disambiguate the user in the user store. This approach gives the authentication scheme the opportunity to modify the login ID before
    SiteMinder
    disambiguates the user.
    If the authentication scheme leaves lpszUserMsg empty,
    SiteMinder
    uses the login ID provided by the Agent (the same behavior as with return code SmAuthApi_NoUserContext).
  • Sm_AuthApi_SuccessUserDN
    The authentication scheme disambiguates the user by constructing the complete DN or search expression and looking up the user in the user store. The authentication scheme passes the user’s complete DN or ODBC database ID to
    SiteMinder
    in lpszUserMsg. Only one DN or database ID can be passed in lpszUserMsg.
  • Sm_AuthApi_SuccessUserFilter
    SiteMinder
    disambiguates the user based upon a standard LDAP search filter that the authentication scheme constructs and passes in lpszUserMsg. When
    SiteMinder
    is passed this return code, it ignores the Start and End field values configured for the user directory.
  • Sm_AuthApi_Attempt
    The user cannot be found in the directory.
  • Sm_AuthApi_Failure
    The error text is returned in lpszUserMsg.
During the user authentication phase,
SiteMinder
calls SmAuthenticate() again after the user context has been established during disambiguation. The function returns one of the following return codes:
  • Sm_AuthApi_Accept
    The user is authenticated.
  • Sm_AuthApi_Reject
    The user is not authenticated.
  • Sm_AuthApi_Challenge
    The user is challenged. The scheme should store the challenge to be presented to the user in lpszUserMsg. Also, a reason code must be supplied in the SM_MAKEAUTH_STATUSVALUE macro. For information about the reason code, see Returns.
  • Sm_AuthApi_Failure
    The error text is returned in lpszUserMsg.
Example: User Authentication Procedure
Sm_AuthApi_Status_t SM_EXTERN SmAuthenticate (
const Sm_Api_Context_t*lpApiContext, 
// The structure that provides API context
const Sm_Api_UserContext_t*lpUserContext, 
// The structure that allows access to user properties
const Sm_AuthApi_UserCredentials_t*lpUserCredentials, 
// The user credentials
unsigned char  bChallengeResponse, 
// Boolean indicating whether this is the response to a challenge
const char*  lpszServerParam,  
// The parameter to be passed to the server
const char* lpszSharedSecret, 
// The shared secret to be passed to the server
const int  nBytesUserMsg,               
// Maximum size of the user message buffer
char*   lpszUserMsg, 
// Output buffer to hold the null-terminated user message
const int  nBytesErrMsg, 
// Maximum size of the error buffer
char*   lpszErrMsg) 
// Output buffer to hold the null-terminated error message
{
if (!lpUserContext->bIsUserContext)
   return Sm_AuthApi_NoUserContext;
return (0 == lpUserContext->fAuthenticate (
             lpUserContext->lpParam,
             lpUserCredentials->lpszPassword,
             nBytesUserMsg,
             lpszUserMsg,
             nBytesErrMsg,
             lpszErrMsg) ? Sm_AuthApi_Accept : Sm_AuthApi_Reject);
}

Release Procedure

To perform any rundown operations the scheme requires,
SiteMinder
calls the release procedure once for each authorization scheme instance. The scheme releases all its resources at this time. The calling sequence specifies two input parameters. You can use one or both of these parameters as best suits your implementation.
Example: Release Procedure
C++
// SmAuthRelease:
// PARAMETERS:
// [in] lpszServerParam:  Parameter string as specified for the authentication scheme.
// [in] lpszSharedSecret: Shared secret string specified in the authentication scheme.
//
// RETURNS:
// Any one of the following Sm_AuthApi_Status_t values:
//   Sm_AuthApi_Success
//   Sm_Authapi_Failure
*/
Sm_AuthApi_Status_t SM_EXTERN SmAuthRelease (
    const char * lpszServerParam,       /* server parameter */
    const char * lpszSharedSecret)      /* server shared secret */
{
    return Sm_AuthApi_Success;
}