Previous Topic: Authentication API for CNext Topic: Tunnel Service API Guidance


Authorization API for C

This section contains the following topics:

Authorization API Overview

Active Expressions

Authorization Function Declarations

Active Expression Examples

Authorization API Overview

Using the Authorization API, you can implement custom access control functionality. To implement custom access control functionality, you must:

  1. Develop a shared library that supports the Authorization API and provides the custom functionality you need.

    The shared library must contain one or more functions defined as exportable symbols. SmApi.h defines all of the data structures necessary to create custom policy, rule, and response plug-ins.

  2. Install the shared library in one of the following default locations:
  3. Define one or more of the following in the Administrative UI:

Include File

When extending the authorization API, include the SmApi.h header file:

#include "SmApi.h"

Active Expressions

An active expression is a string of variable definitions that comprises an active policy, rule, or response. Active expressions are constructed in the Administrative UI using the following syntax:

<@ lib=<lib-spec> func=<func-spec> param=<func-params>@>

In the syntax example:

SiteMinder constructs the active expression from information provided in the Active Rule Editor, Active Policy Editor, or Active Response Attribute Editor dialog box.

How SiteMinder Interprets Active Expressions

An active expression in an application initiates the following tasks:

The specified user-defined function in the shared library returns a result to SiteMinder in the lpszOutBuf parameter. SiteMinder interprets this result according to the type of active expression, as follows:

Define Active Rules

Active rules are defined in the Administrative UI using the Active Rule Editor dialog box. To access this editor from the Rule Properties dialog box, select the Active Rule tab in the Advanced group box, then click Edit.

Define Active Responses

Active responses are defined in the Administrative UI using the Response Attribute Editor dialog box.

From the Response Properties dialog box, access the editor by clicking Create and select the Active Response button in the Attribute Kind group box on the Attribute Setup tab.

Define Active Policies

Active policies are defined in the Administrative UI using the Active Policy Editor dialog box.

From the Policies Properties dialog box, access this editor by selecting the Advanced tab and clicking Edit.

Pass HTTP Headers and Cookies to Policy Server

You can add arbitrary custom key/value pairs to the current session to pass HTTP headers and cookies to the Policy Server. These key/value pairs are kept in the session store; they have the same lifetime as the session. The name/value pairs are stored in the Expiry Data Table in the session store database. There can be maximum 5 entries for a session. The Active Plugin code can use the UserContext structure (Sm_Api_UserContext_t* lpUserContext) to set and retrieve these name/value pairs by calling fSetProp and fGetProp respectively. To set the value, fSetProp is called with lpszPropName as SM_SESSIONVAR(<name>) and lpszValueBuf as the value. To retrieve the value, fGetProp is called with lpszPropName as SM_SESSIONVAR(<name>)/ SM_SESSIONVAR and the value/values is returned in lpszValueBuf.

Note the following:

Authorization Function Declarations

The shared library requires proper entry points. Each entry point in the shared library represents one or more active expressions and must be defined according to the specified syntax.

Note: If you are using Microsoft Visual Studio, export the function addresses to a modular definition file (.DEF) file. To export the function addresses, create a .DEF file, and in the export section of the .DEF file, list the functions that you want to invoke from the Active Rule or Active Policy. After you have created the .DEF file, add it to the Microsoft Visual Studio project.

User-Defined Function

The Policy Server calls a user-defined function to perform a custom policy, rule, or response operation.

You can assign the function any name. Through the active expression that you define in the Administrative UI, you advise SiteMinder of the function name and the name of the shared library where the function resides.

Syntax

int SM_EXTERN <func-spec> (
   const Sm_Api_Context_t*          lpApiContext,
   const Sm_Api_UserContext_t*      lpUserContext,
   const Sm_Api_RequestContext_t*   lpReqContext,
   const char*                      lpszParam,
   const int                        nBytesOutBuf,
   char*                            lpszOutBuf,
   const int                        nBytesErrBuf,
   char*                            lpszErrBuf
);

Parameter

I/O

Description

lpApiContext

I

Pointer to the API context structure.

lpUserContext

I

Pointer to the user context structure.

lpReqContext

I

Pointer to the request context structure.

lpszParam

I

Pointer to the buffer containing the null-terminated parameter string specified in <Param-String>.

nBytesOutBuf

I

Maximum size of the output result buffer (4097 bytes).

lpszOutBuf

O

Output buffer for the result to send to SiteMinder.

nBytesErrBuf

I

Maximum size of the output error buffer (4097 bytes).

lpszErrBuf

O

Output buffer to receive error text. SiteMinder displays the error text in the debug log file.

Returns

SmQueryVersion()

The Policy Server calls this function to determine the Authorization API version that the custom library is compliant with.

Syntax

int SmQueryVersion (
   const Sm_Api_Context_t* lpApiContext
);

Parameter

I/O

Description

lpApiContext

I

A pointer to the API context structure.

Returns

Returns the version number of the Authorization API. Currently the version supported is Sm_Api_Version_V3. This constant is defined in SmApi.h.

Active Expression Examples

This samples provided in the following sections are located in:

sdk\samples\smazapi\smazapi.cpp

The syntax that precedes each sample, such as:

<@ lib="SmAzAPI" func="activeRule" param="" @>

is an example of the Generated Script that SiteMinder constructs in the SiteMinder Active Rule Editor, Active Policy Editor, or Active Response Attribute Editor dialog box from the information you provide in the dialog box.

To build sample active expressions for UNIX, use the makefile found in
<install_path>\sdk\samples\smazapi\makefile.

Example of an Active Rule

The example below returns true if the user has special access permission to view the realm. If the user has directory manager privileges, the user can view the realm.

<@ lib="SmAzAPI" func="activeRule" param="" @>
*************************************************************
int SM_EXTERN activeRule(
const Sm_Api_Context_t* lpApiContext,  
// the structure that provides API context
const Sm_Api_UserContext_t* lpUserContext,  
// the structure that provides user context
const Sm_Api_RequestContext_t* lpReqContext,   
// the structure that provides request context
const char* lpszParam, 
// the parameter string (null-terminated)
const int nBytesOutBuf,   
// the maximum size of the output buffer
char* lpszOutBuf, 
// the output buffer to hold the null-terminated result
const int nBytesErrBuf, 
// the maximum size of the error message buffer
char* lpszErrBuf)     
// the output buffer to hold the null-terminated error message
{
/* User Context is required to use the functions like fGetProp, fSetProp.. */
if(!lpUserContext->bIsUserContext)
   {
   strncpy (lpszErrBuf, "No User Context ", nBytesErrBuf);
   lpszErrBuf[nBytesErrBuf-1] = '\0';
   return -1;
   }
/*
// The DN to look for the attribute "uniquemember"
// If the user is listed as the member of the above attribute,
// it has directory manager privileges.
*/
char lpszDn[] = "cn=Directory Administrators,ou=Groups,o=airius.com";
char lpszDnvalue[256];
memset(lpszDnvalue, 0, sizeof(lpszDnvalue));
/*
// fGetDnProp function is used to retrieve an attribute value
// in a directory entry.
*/
int getResult = lpUserContext->fGetDnProp(
   lpUserContext->lpParam,
   lpszDn,
   "uniquemember",
   sizeof(lpszDnvalue),
   lpszDnvalue);
/*
// If no error occurs, fGenDnProp will return the length of the 
// buffer lpszDnvalue. Otherwise the function returns 0.
*/
if(getResult > 0)
   {

   /* Check to see if the user is present in the list. */
   if(strpbrk(lpszDnvalue, lpUserContext->lpszUserName) != NULL)
      {

      /* The result "true" is placed in the output buffer. */
      strncpy(lpszOutBuf, "true", nBytesOutBuf);
      lpszOutBuf[nBytesOutBuf-1] = '\0';
      return strlen(lpszOutBuf);
      }

      else

      {
      strncpy(lpszOutBuf, "false", nBytesOutBuf);
      lpszOutBuf[nBytesOutBuf-1] = '\0';
      return strlen(lpszOutBuf);
      }
   }
   
   else

   {
   strncpy(lpszErrBuf, "Failed to get attribute value for the DN ",
                        nBytesErrBuf);
   strncat( (lpszErrBuf + strlen(lpszErrBuf)), lpszDn,
             (nBytesErrBuf-strlen(lpszErrBuf)));
   lpszErrBuf[nBytesErrBuf-1] = '\0';
   return -1;
   }

/* everything failed.... */

return 0;

}
Example of an Active Response

This active response returns the common name (cn) of the user, if the user belongs to the organizational unit specified in the parameter (param) field of the active response expression.

<@ lib="SmAzAPI" func="activeResponse" param="Human Resources" @>
***********************************************************
int SM_EXTERN activeResponse(
const Sm_Api_Context_t*   lpApiContext,   
/* the structure that provides API context */
const Sm_Api_UserContext_t*  lpUserContext, 
/* the structure that provides user context */
const Sm_Api_RequestContext_t*  lpReqContext,   
/* the structure that provides request context */
const char* lpszParam,      
/* the parameter string (null-terminated) */
const int  nBytesOutBuf,   
/* the maximum size of the output buffer */
char*  lpszOutBuf,     
/* the output buffer to hold the null-terminated attribute value */
const int   nBytesErrBuf,   
/* the maximum size of the error message buffer */
char*   lpszErrBuf)     
/* the output buffer to hold the null-terminated error message */
{
memset(lpszOutBuf, 0, sizeof(lpszOutBuf));
if(!lpUserContext->bIsUserContext)
      {
      strncpy (lpszErrBuf, "No User Context ", nBytesErrBuf);
      lpszErrBuf[nBytesErrBuf-1] = '\0';
      return -1;
      }
/* Store all the organizational units to which the user belongs. */
char lpszOrgUnit[30];
memset(lpszOrgUnit, 0, sizeof(lpszOrgUnit));
/* store the common name of the user. */
char lpszCN[30];
memset(lpszCN, 0, sizeof(lpszCN));
/* Check to see if a parameter is requested. */
if(lpszParam == NULL || strlen(lpszParam) == 0) 
   {
   strncpy (lpszErrBuf, "Organizational unit is not entered ",
            nBytesErrBuf);
   lpszErrBuf[nBytesErrBuf-1] = '\0';
   return -1;
   }
/* Get all the organization units to which the user belongs. */
int getResult = lpUserContext->fGetProp (
   lpUserContext->lpParam,
   "ou",              /* Attribute name */
   sizeof (lpszOrgUnit), lpszOrgUnit);
if (getResult < 0)
   {
   strncpy (lpszErrBuf, 
        "Failed to get organization unit for the user's profile ",
        nBytesErrBuf);
   strncat( (lpszErrBuf + strlen(lpszErrBuf)), 
            lpUserContext->lpszUserName, 
            (nBytesErrBuf-strlen(lpszErrBuf)));
   lpszErrBuf[nBytesErrBuf-1] = '\0';
   return -1;
   }
    else
    {
/* Check if the user belongs to the organization unit that is requested. */
   if(strstr(lpszOrgUnit, lpszParam) != NULL)
      {
      if((lpUserContext->fGetProp(lpUserContext->lpParam,
           "cn",sizeof(lpszCN),lpszCN)) > 0)
         {
         strncpy(lpszOutBuf, lpszCN, nBytesOutBuf);
         lpszOutBuf[nBytesOutBuf-1] = '\0';
         return strlen(lpszOutBuf);
         } /* end of fGetProp */
         else
         {
         strncpy (lpszErrBuf, 
          "Failed to get user common name from user's profile attribute ",
           nBytesErrBuf);
         strncat( (lpszErrBuf + strlen(lpszErrBuf)),
                    lpUserContext->lpszUserName, 
                    (nBytesErrBuf-strlen(lpszErrBuf)));
         lpszErrBuf[nBytesErrBuf-1] = '\0';
         return -1;
         }
        } /* end of strstr */
        else
        {
      strncpy (lpszErrBuf, 
       "The user does not belong to the requested organizational unit ", 
        nBytesErrBuf);
      lpszErrBuf[nBytesErrBuf-1] = '\0';
      return -1;
      }
   }
    /* everything failed.... */
    return 0;
 }
#ifndef _WIN32
}

#endif