Skip to content

Domino Web Server Application Interface (DSAPI)

Chapter 9-11
Domino Web Server Application Interface (DSAPI)

Overview

The Domino Web Server Application Programming Interface (DSAPI) is a C API that lets you write your own extensions to the Domino Web Server. DSAPI extensions, or filters, are notified whenever a particular event occurs during the processing of an http request.

A DSAPI filter allows you to customize the processing of an http request when particular events occur. The http stack notifies the filter(s) of the event. There are currently 13 events that can be captured by a DSAPI filter. Depending on the design and its implementation, a filter can support one or any number of events.

The implementation of the DSAPI interface relies on the filter to indicate which of the events it supports. The filter then receives notifications only for those events it claims it supports.

Please refer to the HCL C API Reference for further information on any of the filter data structures referred to in this document.

Getting Started

A DSAPI filter must specify two entry points:

  1. Initialization
  2. Event Notification


An optional entry point may be defined for filter termination. Also, optional entry points may be defined for thread initialization and termination.

Initialization

Domino calls the Initialization function when the filter is loaded. The filter is loaded when the Domino HTTP server task is started or when the HTTP task is restarted with the Domino console command, "tell http restart". The prototype of the Initialization function is:
/---
* filter initialization
/
unsigned int FilterInit(FilterInitData pFilterInitData);

The name of the Initialization function must be FilterInit for the DSAPI layer to find it when it loads the filter.

Refer to the HCL C API Reference for further information on the FilterInitData structure.

Event Notification

The Event Notification function does the actual work of the filter. Domino calls the Event Notification function whenever a particular event occurs during the processing of an http request. When Domino calls the filter's Event Notification function it passes information about the request and the event being processed. On each call the filter can decide to handle the event, with or without an error return, or decline to handle the event. The prototype for the Event Notification function is:
/
---
* filter notification handling
/
unsigned int HttpFilterProc(FilterContext
pContext, unsigned int eventType, void pEventData);

The name of the event handling function must be HttpFilterProc for the DSAPI layer to find it when it loads the filter.

pContext is a pointer to the FilterContext that contains information about the http request, server callback function pointers, and a pointer to the filter's own data context. Refer to the HCL C API Reference for further information on the FilterContext structure.

eventType indicates which event is occurring.

pEventData is a pointer to a structure associated with the event. There is a different event data structure for each event. See the Events section below for details.


Optional Thread Initialization and Termination

The filter may also define entry points for the initialization and termination of threads. The http stack will call the function HttpFilterThreadInit after calling the initialization function FilterInit. HttpFilterThreadInit is mostly used to initialize any thread locals. The prototype of the Filter Thread Initialization function is:

unsigned int HttpFilterThreadInit (int threadType);

The Filter Thread Initialization function requires the Filter Thread Termination function. This function will be called when the library is unloaded to allow the filter to deallocate any of the resources allocated by the Filter Thread Initialization function. The prototype of the Filter Thread Termination function is:

unsigned int HttpFilterThreadTerm ( int threadType );

Optional Termination

The filter may also define a Termination entry point. Domino will call this function whenever the filter is about to be unloaded - when the http stack process is shutting down. The filter can use this function to clean up resources it allocated. The filter must deallocate all global resources it allocated when its initialization routine was called. The prototype of the Filter Termination function is:
/
---
* filter termination
*/
unsigned int TerminateFilter(unsigned int reserved);

All the exported functions return an unsigned int status code. The possible values of the status code are as follows:

  • kFilterHandledRequest signals that the http request has completely been processed. A response has already been sent to the client, and the http stack must terminate the processing of the request.
  • kFilterHandledEvent signals that the event has been handled, but further processing is to take place to completely service the http request.
  • kFilterNotHandled signals that the filter did not process the event.
  • kFilterError signals that the filter encountered an error while processing the event. In this case the http stack is to stop processing the request, and send an appropriate error response to the user.


Note that for the functions FilterInit, HttpFilterThreadInit, HttpFilterThreadTerm, and TerminateFilter, the only possible return codes are kFilterHandledEvent and kFilterError. The function HttpFilterProc can return any of the status codes when handling an event.

Events

Events occur in a specific sequence. They reflect the state of the http stack at each of its processing steps. Event notifications can be seen as an opportunity for a filter(s) to override the default implementation of a given processing step. With each event, a structure, which contains additional information and in most cases additional callback functions, is passed to the filter's event notification handling routine. The filter can call the callback functions to get additional information or to have a service performed. The event notification routine is only called for those events the filter is registered for (those that were passed in the FilterInitData structure when the filter was loaded and initialized). Events are described below in the sequence in which they happen.

kFilterStartRequest Event
This event is used to advise all filters currently loaded that an http request has been received, and is about to be processed. A filter, in this step, can prepare itself for processing the request. Typically in this step, the filters should allocate its own private context data, and required resources necessary to handle the processing of a request. The argument, pEventData, is not used and a NULL is passed. Any filter supporting this event should return the value, kFilterHandledEvent.

kFilterRawRequest Event
All filters currently loaded and supporting this event are notified that all the input http headers have been read in. Any filter that needs to preprocess the input headers can do so at this time. Note that a filter could choose to completely service the http request at this time. The argument, pEventData, is a pointer to the FilterRawRequest structure. The structure FilterRawRequest is described below:

      typedef struct {

unsigned int requestMethod;


      int ( *GetAllHeaders )( FilterContext *pContext,
      char** ppHeaders,
      unsigned int *pErrID );

      int ( *GetHeader )( FilterContext *pContext,
      char *pName,
      char *pBuffer,
      unsigned int bufferSize,
      unsigned int *pErrID );

      int ( *SetHeader )( FilterContext *pContext,
      char *pName,
      char *pValue,
      unsigned int *pErrID );

      int ( *AddHeader )( FilterContext *pContext,
      char *pHheader,
      unsigned int *pErrID );

      unsigned int reserved;
      } FilterRawRequest;

      requestMethod: is the request method. It can be one of the following:
          kRequestNone: No HTTP request method is provided.
          kRequestHEAD: Method is often used for testing hypertext links for validity, accessibility, and recent modification.
          kRequestGET: GET method - used to retrieve whatever information (in the form of an entity) is identified by the Request-URL.
          kRequestPOST: POST method - requests that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URL in the Request-Line.
          kRequestPUT: PUT method - requests that the enclosed entity be stored under the supplied Request-URL.
          kRequestDELETE: DELETE method - requests that the origin server delete the resource identified by the Request-URL.
          kRequestTRACE: TRACE method.
          kRequestCONNECT: CONNECT method.
          kRequestOPTIONS: OPTIONS method.
          kRequestUNKNOWN: Unknown request method.
          kRequestBAD: Bad request method. Error.
      int ( *GetAllHeaders )( FilterContext *pContext,
      char** ppHeaders,
      unsigned int *pErrID );
        This callback function allows the filter to gain access to the input http headers.

        Returns the byte count of the buffer containing the http headers.

        pContext is a pointer to the structure, FilterContext, and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        ppHeaders is a pointer to a location where the DSAPI layer will store the pointer to a buffer that will contain the input http headers. The format for the http headers is the following: "<header1><\r\n><header2><\r\n>....<headern><\r\n><\r\n>".

        pErrID is a pointer to an unsigned integer that is set to 0 if successful, to an error code otherwise. Possible error codes are: DSAPI_INVALID_ARGUMENT, DSAPI_MEMORY_ERROR and DSAPI_INTERNAL_ERROR.

      int ( *GetHeader )( FilterContext *pContext,
      char *pName,
      char *pBuffer,
      unsigned int bufferSize,
      unsigned int *pErrID );
        This callback function retrieves a single http header value. The http header name is supplied. If the http header does not exist, an empty string is returned in the supplied buffer.

        Returns 0 for a hard failure (bad argument passed), the number of bytes valid in the buffer containing the result if successful, or the required buffer size if the buffer is too small to contain the result.

        pContext is a pointer to the structure, FilterContext, and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        pName is a pointer to a string containing the name of the desired http header. This cannot be NULL or an empty string.

        pBuffer is a pointer to a buffer where to store the result. This argument cannot be NULL.

        bufferSize is the size of supplied buffer.

        pErrID is a pointer to an unsigned integer that is set to 0 if successful, to DSAPI_BUFFER_TOO_SMALL if the supplied buffer is too small to contain the result, and DSAPI_INVALID_ARGUMENT for invalid arguments passed.
      int ( *SetHeader )( FilterContext *pContext,
      char *pName,
      char *pValue,
      unsigned int *pErrID );
        This callback function allows a filter to change the value of an existing input http header. Note that if the http header does not exist, it is added to the list of input headers.

        Returns TRUE if successful, FALSE otherwise.

        pContext is a pointer to the structure, FilterContext, and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        pName is a pointer to a string containing the name of the http header to change. This argument cannot be NULL or an empty string.

        pValue is a pointer to a string containing the value for the http header.

        pErrID is a pointer to an unsigned integer where to store a status code. The status code is set to 0 if the operation is successful, to a non-zero value otherwise.

      int ( *AddHeader )( FilterContext *pContext,
      char *pHheader,
      unsigned int *pErrID );
        This callback function allows a filter to add an http header to the list of the input http headers. Note that if the http header already exists, its value is changed to reflect the new value.

        Return TRUE if successful, FALSE otherwise.

        pContext is a pointer to the structure, FilterContext, and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        pHeader is a pointer to a valid http header. The expected format is the same as the format of input http headers, i.e., <headerName:value>.

        pErrID is a pointer to an unsigned integer where to store a status code. The status code is set to 0 if the operation is successful, to a non-zero value otherwise. The only valid non-zero status in this case is DSAPI_INVALID_ARGUMENT which indicates that an error in the format of the supplied header has been detected.

      reserved is reserved for future use.

kFilterParsedRequest Event
All filters currently loaded and supporting this event, are notified with this event when the http stack has finished pre-parsing all the http input headers. Note that this reflects the same state as in the event kFilterRawRequest since the http stack pre-parses the http input headers before it starts calling any filter. Any filter once again can choose to process the request completely at this step. pEventData is a pointer to the structure, FilterParsedRequest. Note that only two callback functions are provided. You can only access the http input headers in this step. With the kFilterRawRequest, you have the opportunity to change them as well.

      typedef struct {
      unsigned int requestMethod;

      int ( *GetAllHeaders )( FilterContext *pContext,
      char **ppHeaders,
                          unsigned int *pErrID );
      int ( *GetHeader )( FilterContext *pContext,
      char *pName,
      char *pBuffer,
      unsigned int bufferSize,
      unsigned int *pErrID );

      unsigned int reserved;
      } FilterParsedRequest;

      requestMethod: is the request method. It can be one of the following:
          kRequestNone: No HTTP request method is provided.
          kRequestHEAD: Method is often used for testing hypertext links for validity, accessibility, and recent modification.
          kRequestGET: GET method - used to retrieve whatever information (in the form of an entity) is identified by the Request-URL.
          kRequestPOST: POST method - requests that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URL in the Request-Line.
          kRequestPUT: PUT method - requests that the enclosed entity be stored under the supplied Request-URL.
          kRequestDELETE: DELETE method - requests that the origin server delete the resource identified by the Request-URL.
          kRequestTRACE: TRACE method.
          kRequestCONNECT: CONNECT method.
          kRequestOPTIONS: OPTIONS method.
          kRequestUNKNOWN: Unknown request method.
          kRequestBAD: Bad request method. Error.
      int ( *GetAllHeaders )( FilterContext *pContext,
      char** ppHeaders,
      unsigned int *pErrID );
        This callback function allows the filter to gain access to the input http headers.

        Returns the byte count of the buffer containing the http input headers.

        pContext is a pointer to the structure, FilterContext, and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        ppHeaders is a pointer to a location where the DSAPI layer will store the pointer to a buffer that will contain the input http headers. The format for the http headers is the following: "<header1><\r\n><header2><\r\n>....<headern><\r\n><\r\n>".

        pErrID is a pointer to an unsigned integer that is set to 0 if successful, to an error code otherwise. Possible error codes are: DSAPI_INVALID_ARGUMENT, DSAPI_MEMORY_ERROR and DSAPI_INTERNAL_ERROR.

      int ( *GetHeader )( FilterContext *pContext,
      char *pName,
      char *pBuffer,
      unsigned int bufferSize,
      unsigned int *pErrID );
        This callback function retrieves a single http header value. The http header name is supplied. If the http header does not exist, an empty string is returned in the supplied buffer.

        Returns 0 for a hard failure (bad argument passed), the number of bytes valid in the buffer containing the result if successful, or the required buffer size if the buffer is too small to contain the result.

        pContext is a pointer to the structure, FilterContext, and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        pName is a pointer to a string containing the name of the desired http header. This cannot be NULL or an empty string.

        pBuffer is a pointer to a buffer where to store the result. This argument cannot be NULL.

        bufferSize is the size of supplied buffer.

        pErrID is a pointer to an unsigned integer that is set to 0 if successful, to DSAPI_BUFFER_TOO_SMALL if the supplied buffer is too small to contain the result, and DSAPI_INVALID_ARGUMENT for invalid arguments passed.

kFilterRewriteURL Event
All filters currently loaded and supporting this event have the opportunity to change the URL to redirect the request to some other resource. If a filter successfully rewrites the URL to be processed, and the server processes the new URL, then the DSAPI layer stops processing this event, i.e., no other filters in the list are notified. pEventData is a pointer to an instance of the structure, FilterMapURL. Note that the structure, FilterMapURL is also used in the events, kFilterTranslateRequest and kFilterPostTranslate.

      typedef struct {
      const char* url;
      char* pathBuffer;
      unsigned int bufferSize;
      unsigned int mapType;
      } FilterMapURL;

      url: Input parameter. It is a pointer to a string whose value is the current URL being processed.

      pathBuffer: Output parameter. It is a pointer to a supplied buffer where the new URL is to be stored.

      bufferSize: Input parameter. This is the size of the supplied buffer in which to store the new URL.

      mapType: Output parameter. Not used in this case.


kFilterAuthenticate Event
This event occurs when the http stack is in the authentication phase of the process. The filter code can view the request and user credentials, authenticate the user for the http stack, or completely handle the request. pEventData is a pointer to an instance of the structure.

      typedef struct {
      LMBCS* userName;
      LMBCS* password;
      unsigned char* clientCert;
      unsigned int clientCertLen;
      unsigned int authFlags;
      unsigned int preAuthenticated;
      unsigned int foundInCache;
      unsigned int authNameSize;
      LMBCS* authName;
      unsigned int authType;

      int ( *GetUserNameList )( FilterContext *pContext,
                            LMBCS *pBuffer,
      unsigned int bufferSize,
      unsigned int *pNumNames,
      unsigned int reserved,
      unsigned int *pErrID );

      int ( *GetHeader )( FilterContext *pContext,

char *pName,

      char *pBuffer,
      unsigned int bufferSize,
      unsigned int *pErrID );


void ( GetMappedResource )( FilterContext pContext,
char *ppBuffer,
unsigned int
pErrID );

      } FilterAuthenticate;

      userName: Input parameter. The user's web name from the input request. It is set to NULL if none is available.

      password: Input parameter. The user's web password from the input request. It is set to NULL if none is available.

      clientCert : Input parameter. The SSL client certification. It is set to NULL if none is available.

      clientCertLen: Input parameter. The length of the SSL client certificate. It is set to zero in none is available.

      authFlags: Input parameter. The authentication options that are enabled for the server. It can be one of more of the following "OR"ed together:
          kAuthAllowBasic: The server allows basic authentication by providing a user name and password.
          kAuthAllowAnonymous: The server allows anonymous access to public (non protected) documents.
          kAuthAllowSSLCert: The server allows SSL authentication using an SSL client certificate.
          kAuthAllowSSLBasic:
          kAuthAllowSSLAnonymous: The server allows anonymous SSL authentication to public (non protected) documents.
          kAuthRedirectToSSL: The server allows redirection to SSL authentication for documents that are SSL protected.
      preAuthenticated: Input parameter. It is set to TRUE if the user has been already pre-authenticated presumably by a companion http stack (e.g., MS-IIS).

      foundInCache: Input parameter. It is set to TRUE if the user is already cached in Domino's internal cache and will be authenticated on that basis unless the filter handles the event. This member allows filters not to re-authenticate an already authenticated user. Filters in this case should immediately return kFilterNotHandled.

      authNameSize: Input parameter. This is the size of the buffer in which to store the authenticated user name.

      authName: Input parameter. It is a pointer to a supplied buffer where the authenticated user's name (canonical name) must be stored.

      authType: Output parameter. The filter, if it handles the event, must set this field to the type of authorization described by one of the following values:
        kNotAuthentic: User's credentials failed authentication. The http stack must terminate the processing of the request.
        kAuthenticBasic: User's name and password has passed authentication. The authentication phase should be terminated, and the next phase in the processing of the request started.
        kAuthenticClientCert: The SSL authentication using an SSL client certificate has succeeded. The authentication phase should be terminated, and the next phase in the processing of the request started.
      int ( *GetUserNameList )( FilterContext *pContext,
      LMBCS *pBuffer,
      unsigned int bufferSize,
                        unsigned int *pNumNames,
      unsigned int reserved,
      unsigned int *pErrID );
        This callback function allows a filter to gain access to the user's group list.

        Returns the number of bytes valid in the return buffer, -1 if the buffer is too small (the buffer is still filled to end).

        pContext is a pointer to the structure, FilterContext and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        pBuffer is a pointer to a memory buffer where to return the user's group list after it has been computed. The format is a sequence of zero terminated strings, i.e, "<group1\0group2\0...groupn\0".

        bufferSize is the size of the memory block pointed to by pBuffer.

        pNumNames is a pointer where to store the number of names contained in the user's group name list.

        reserved is reserved for future use. It should be set to 0.

        pErrID is a pointer to an unsigned integer where to store a status code. The status code is set to 0 if the operation is successful, to a non-zero value otherwise. The only valid non-zero status in this case is DSAPI_INVALID_ARGUMENT which indicates that one or more of the supplied arguments is(are) not valid.

      int ( *GetHeader )( FilterContext *pContext,
      char *pName,
      char *pBuffer,
      unsigned int bufferSize,
      unsigned int *pErrID );
        This callback function retrieves a single http header value. The http header name is supplied. If the http header does not exist, an empty string is returned in the supplied buffer.

        Returns 0 for a hard failure (bad argument passed), the number of bytes valid in the buffer containing the result if successful, or the required buffer size if the buffer is too small to contain the result.

        pContext is a pointer to the structure, FilterContext, and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        pName is a pointer to a string containing the name of the desired http header. This cannot be NULL or an empty string.

        pBuffer is a pointer to a buffer where to store the result. This argument cannot be NULL.

        bufferSize is the size of supplied buffer.

        pErrID is a pointer to an unsigned integer that is set to 0 if successful, to DSAPI_BUFFER_TOO_SMALL if the supplied buffer is too small to contain the result, and DSAPI_INVALID_ARGUMENT for invalid arguments passed.
      void ( *GetMappedResource )( FilterContext *pContext,
      char **ppBuffer,
      unsigned int *pErrID );
        The GetMappedResource callback function retreives a mapped resource value.

        Returns 0 for for a hard failure (bad argument passed), the number of bytes valid in the buffer containing the result if successful, or the required buffer size if the buffer is too small to contain the result.

        pContext - pointer to the structure FilterContext and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.
        ppBuffer - pointer to a pointer to a buffer where to store the result. This argument cannot be NULL.
        pErrID - pointer to an unsigned integer that is set to 0 if successful, to DSAPI_BUFFER_TOO_SMALL if the supplied buffer is too small to contain the result.


kFilterUserNameList Event
This event occurs when the http stack is about to generate the user's group name list. These are group names the user is a member of. This event follows the kFilterAuthenticate event. The filter can have the Domino server populate the list, add or remove groups to/from the list or completely handle the event (generate completely the group list itself). The parameter in the function, HttpEventProc, pEventData, is a pointer to the structure, FilterUserNameList.

      typedef struct {
      const LMBCS* userName;

      int ( *GetUserNameList )( FilterContext *pContext,
      LMBCS *pBuffer,
      unsigned int bufferSize,
      unsigned int *pNumNames,
      unsigned int reserved,
      unsigned int *pErrID );

      int ( *PopulateUserNameList )( FilterContext *pContext,
      LMBCS *pBuffer,
      unsigned int bufferSize,
      unsigned int *pNumNames,
      unsigned int reserved,
      unsigned int *pErrID );

      int ( *AddGroupsToList )( FilterContext *pCcontext,
      LMBCS *pGroupNames,
      unsigned int numGroupNames,
      unsigned int reserved,
      unsigned int *pErrID );

      int ( *RemoveGroupsFromList )( FilterContext *pContext,
      unsigned int reserved,
      unsigned int *pErrID );

      unsigned int reserved;
      } FilterUserNameList;

      userName: the authenticated user name.

      int ( *GetUserNameList )( FilterContext *pContext,
      LMBCS *pBuffer,
      unsigned int bufferSize,
      unsigned int *pNumNames,
      unsigned int reserved,
      unsigned int *pErrID );
        This callback function allows a filter to gain access to the user's group list.

        Returns the number of bytes valid in the supplied buffer, (-1) if the buffer is too small (although the buffer is filled to end).

        pContext is a pointer to the structure, FilterContext, and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        pBuffer is a pointer to a memory buffer where to return the user's group list after it has been computed. The format is sequence of zero terminated strings, i.e., "<group1\0group2\n...groupn\0>".

        bufferSize is the size of the memory block pointed to by pBuffer.

        pNumNames is a pointer where to store the number of names contained in the user's group list.

        reserved is reserved for future use. It should be set to 0.

        pErrID is a pointer to an unsigned integer where to store a status code. The status code is set to 0 if the operation is successful, to a non-zero value otherwise. The only valid non-zero status in this case is DSAPI_INVALID_ARGUMENT which indicates that one or more of the supplied arguments is(are) not valid.

      int ( *PopulateUserNameList )( FilterContext *pContext,
      LMBCS *pBuffer,
      unsigned int bufferSize,
      unsigned int *pNumNames,
      unsigned int reserved,
      unsigned int *pErrID );
        This callback function allows a filter to request that the user's group list be computed and returned in the supplied buffer.

        Returns the number of valid bytes returned in pBuffer.

        pContext is a pointer to the structure, FilterContext, and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        pBuffer is a pointer to a memory buffer where to return the user's group list after it has been computed.

        bufferSize is the size of the memory block pointed to by pBuffer.

        pNumNames is a pointer where to store the number of names contained in the user's group list.

        reserved is reserved for future use. It should be set to 0.

        pErrID is a pointer to an unsigned integer where to store a status code. The status code is set to 0 if the operation is successful, to a non-zero value otherwise.

      int ( *AddGroupsToList )( FilterContext *pCcontext,
      LMBCS *pGroupNames,
      unsigned int numGroupNames,
      unsigned int reserved,
      unsigned int *pErrID );
        This callback function allows the filter to dynamically augment the user's group.

        Returns TRUE if successful, FALSE otherwise

        pContext is a pointer to the structure, FilterContext, and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        pBuffer is a pointer to a buffer that contains the names to add to the user's group list. The format is a list of strings each of which contains the group name, i.e., < string1 string2 ... stringn >. Strings here are defined as C strings, i.e., a NULL terminated sequence of bytes.

        numGroupName is the number of group names contained in the pBuffer.

        reserved is reserved for future use. It should be set to 0.

        pErrID a pointer to an unsigned integer where to store a status code. The status code is set to 0 if the operation is successful, to a non-zero value otherwise. In this case it is always set to 0.

      int ( *RemoveGroupsFromList )( FilterContext *pContext,
      unsigned int reserved,
      unsigned int *pErrID );
        This callback allows the filter to clear the user's group list. The result is a group list that contains only the user's known names.

        Return TRUE

        pContext is a pointer to the structure, FilterContext, and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

        reserved is reserved and should be always set to 0.

        pErrID is a pointer to an unsigned integer where to store a status code. The status code is always set to 0.

      reserved: is reserved for future use.

Note that the altered group names list is not seen by the current implementation of Domino's agents (agents compute their own group names list based on the authenticated user name).


kFilterTranslateRequest Event
This event occurs when the http stack is about to translate the path URL to a target resource. The filter can translate the request using its own translation and mapping rules, or completely handle the request. pEventData points to an instance of the structure, FilterMapURL. The structure, FilterMapURL, is described below:

      typedef struct {
      const char* url;
      char* pathBuffer;
      unsigned int bufferSize;
      unsigned int mapType;
      } FilterMapURL;

      url: Input parameter. It is a pointer to a string whose value is the current URL being processed.

      pathBuffer: Output parameter. It is a pointer to a supplied buffer where the resulting target resource path is to be stored.

      bufferSize: Input parameter. This is the size of the supplied buffer in which to store the target resource path .

      mapType: Output parameter. It is one of the following:
typedef enum {<br>
    kURLMapUnknown  = 0,<br>
    kURLMapPass = 1,    <br>
    kURLMapExec = 2,<br>
    kURLMapRedirect = 3,<br>
    kURLMapService = 4,<br>
    kURLMapDomino = 5<br>
    } FilterURLMapTypes;<br>


where

          kURLMapUnknown: Unknown mapping type.
          kURLMapPass: File system mapping rule
          kURLMapExec: CGI mapping rule
          kURLMapRedirect: Redirect mapping rule
          kURLMapService: Obsolete. No longer used.
          kURLMapDomino: Domino mapping rule

Note: The kFilterMapURL event is the same as the KFilterTranslateRequest event.


kFilterPostTranslate Event
This event occurs after the event, kFilterTranslateEvent, has been handled. It is an opportunity for the filter to change the target resource to be accessed. The filter can change both the target resource path and the mapping type. The filter can also choose to completely service the request. pEventData is a pointer to the structure, FilterMapURL. The structure, FilterMapURL, is described below:

      typedef struct {
      const char* url;
      char* pathBuffer;
      unsigned int bufferSize;
      unsigned int mapType;
      } FilterMapURL;

      url: Input parameter. It is a pointer to a string whose value is the current URL being processed.

      pathBuffer: Input/Output parameter. It is a pointer to a supplied buffer containing the already computed path to the target resource. The new target resource path is to be stored in this buffer.

      bufferSize: Input parameter. This is the size of the supplied buffer in which to store the target resource path .

      mapType: Input/Output parameter. It is one of the following:
typedef enum {<br>
    kURLMapUnknown  = 0,<br>
    kURLMapPass = 1,    <br>
    kURLMapExec = 2,<br>
    kURLMapRedirect = 3,<br>
    kURLMapService = 4,<br>
    kURLMapDomino = 5<br>
    } FilterURLMapTypes;<br>


where

          kURLMapUnknown: Unknown mapping type.
          kURLMapPass: File system mapping rule
          kURLMapExec: CGI mapping rule
          kURLMapRedirect: Redirect mapping rule
          kURLMapService: Obsolete. No longer used.
          kURLMapDomino: Domino mapping rule

kFilterAuthorized Event
This event occurs after the authentication phase has taken place and the user's group names list has been computed. The filter can override the default implementation of the authorization phase and grant or deny access to the target resource. pEventData is a pointer to the structure, FilterAuthorize. It contains information about the target resource to serve. Note that the filter can get access to the authenticated user information by using the services via the ServerSupport callback with the flag, kGetAuthenticatedUserInfo. This will allow the user to gain access to the user's authenticated name as well as to his/her group names list.

If the filter denies access to the target resource, it must send the appropriate response to the client, and set the field, isAuthorized, in the FilterAuthorize structure to 0. It can then return either kFilterHandledRequest or kFilterHandledEvent. The DSAPI layer will then signal the http stack to terminate the processing of the current request.

The structure FilterAuthorize is described below:

      typedef struct _FilterAuthorize{
      const char *pURL;
      char *pBuffer;
      unsigned int bufferSize;
      unsigned int mapType;
      unsigned int isAuthorized;
      } FilterAuthorize;


      pURL: Input parameter. It is the http request URL.

      pBuffer: Input parameter. This buffer contains the path to the target resource.

      bufferSize: Input parameter. This is the total size in bytes of the supplied buffer.

      mapType: Input parameter. It is one of the following:
          typedef enum {
    kURLMapUnknown  = 0,<br>
    kURLMapPass = 1,    <br>
    kURLMapExec = 2,<br>
    kURLMapRedirect = 3,<br>
    kURLMapService = 4,<br>
    kURLMapDomino = 5<br>
    } FilterURLMapTypes;<br>


where

          kURLMapUnknown: Unknown mapping type.
          kURLMapPass: File system mapping rule
          kURLMapExec: CGI mapping rule
          kURLMapRedirect: Redirect mapping rule
          kURLMapService: Obsolete. No longer used.
          kURLMapDomino: Domino mapping rule
      isAuthorized: Output parameter. It is set to 1 if the user is granted access to the resource, 0 otherwise.



kFilterProcessRequest Event
This is the last step in servicing an http request. This event can be used to override the default implementation of the processing of the request. In this phase the response data is computed and sent to the client. pEventData is a pointer to the structure, FilterMapURL. The structure, FilterMapURL, is described below:

      typedef struct {
      const char* url;
      char* pathBuffer;
      unsigned int bufferSize;
      unsigned int mapType;
      } FilterMapURL;

      url: Input parameter. It is a pointer to a string whose value is the current URL being processed.

      pathBuffer: Input parameter. It is a pointer to a supplied buffer containing the already computed path to the target resource.

      bufferSize: Input parameter. This is the size of the supplied buffer in which to store the target resource path.

      mapType: Input parameter. It is one of the following:
typedef enum {<br>
    kURLMapUnknown  = 0,<br>
    kURLMapPass = 1,    <br>
    kURLMapExec = 2,<br>
    kURLMapRedirect = 3,<br>
    kURLMapService = 4,<br>
    kURLMapDomino = 5<br>
    } FilterURLMapTypes;<br>


where

          kURLMapUnknown: Unknown mapping type.
          kURLMapPass: File system mapping rule
          kURLMapExec: CGI mapping rule
          kURLMapRedirect: Redirect mapping rule
          kURLMapService: Obsolete. No longer used.
          kURLMapDomino: Domino mapping rule

kFilterEndRequest Event
This event is used to advise the filter code that it is time to clean up and release resources allocated to handle a given http request. pEventData is NULL in this case.

kFilterAuthUser Event
This event is replaced with the kFilterAuthenticate event, but is still supported for compatibility with previously written DSAPI filters. In this event, the filter authenticates the web user. pEventData is an instance of the structure, FilterAuthenticate. The structure is described fully in the kFilterAuthenticate event described above.

This event allows you to customize the authentication of the Web users, which is often one part of implementing 'single-sign on' within a corporation. In this case, the DSAPI filter is notified when Domino authenticates a user. The DSAPI filter can then parse the user name, validate user names and passwords against a legacy mainframe system, and if successful, notify the Domino Web server that it has handled the user's authentication and return to Domino the user's credentials.

This is a guide to setting the output variables and return code for common authentication scenarios where eventData points to the FilterAuthenticate structure:

  • Scenario 1: The filter was able to authenticate the user.
    Set eventData->authName to the canonical name, set eventData->authType to kAuthenticBasic or kAuthenticClientCert, and the return code to kFilterHandledEvent.
  • Scenario 2: The filter was NOT able to authenticate the user, and other filters or Domino should go ahead and attempt their own authentication.
    Set the return code to kFilterNotHandled.
  • Scenario 3: The filter was NOT able to authenticate the user, and other filters or Domino should NOT attempt their own authentication.
    Set eventData->authType to kNotAuthentic, and the return code to kFilterHandledEvent.

kFilterResponse Event
This event occurs when the http stack is about to send the http response headers to the client. This gives a chance to the filter to change the response that is sent to the client. This is not completely implemented in the current version of DSAPI. pEventData is a pointer to an instance of the structure FilterResponse and is described below:

typedef struct {
unsigned int responseCode;
char reasonText;

int (
GetAllHeaders )( FilterContext pContext,
char
ppHeaders,
unsigned int
pErrID );

int ( GetHeader )( FilterContext pContext,
char pName,
char
pBuffer,
unsigned int bufferSize,
unsigned int pErrID );

int (
SetHeader )( FilterContext pContext,
char
pName,
char pValue,
unsigned int
pErrID );

int ( AddHeader )( FilterContext pContext,
char pHeader,
unsigned int
pErrID );

unsigned int reserved;
char userName;
} FilterResponse;

responseCode - Input parameter. It is the HTTP Response status code.

reasonText - Input parameter. It is the HTTP response status text if any.

int (
GetAllHeaders )( FilterContext pContext,
char
ppHeaders,
unsigned int
pErrID );
This callback function allows the filter to gain access to the response http headers.

Returns the byte count of the buffer containing the http response headers.

pContext - is a pointer to the structure FilterContext and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

ppHeaders - is a pointer to a location where the DSAPI layer will store the pointer to a buffer that will contain the response http headers.

pErrID - is a pointer to an unsigned integer that is set to 0 if successfull, to an error code otherwise. Possible error codes are: DSAPI_INVALID_ARGUMENT, DSAPI_MEMORY_ERROR and DSAPI_INTERNAL_ERROR.

int ( GetHeader )( FilterContext pContext,
char pName,
char
pBuffer,
unsigned int bufferSize,
unsigned int pErrID );
This callback function retreives a single http response header value. The http header name is supplied. If the http header does not exist, an empty string is returned in the supplied buffer.

Returns 0 for for a hard failure (bad argument passed), the number of bytes valid in the buffer containing the result if successfull, or the required buffer size if the buffer is too small to contain the result.

pContext - is a pointer to the structure FilterContext and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

pName - is a pointer to a string containing the name of the desired http header. This cannot be equal to NULL nor to an empty string.

pBuffer - is a pointer to a buffer where to store the result. This argument cannot be NULL.

bufferSize - is the size of supplied buffer.

pErrID - is a pointer to an unsigned integer that is set to 0 if successfull, to DSAPI_BUFFER_TOO_SMALL if the supplied buffer is too small to contain the result.

int (
SetHeader )( FilterContext pContext,
char
pName,
char pValue,
unsigned int
pErrID );
This callback function allows a filter to change the value of an existing response http header. Note that if the http header does not exist, it is added to the list of http response headers.

Returns TRUE if successfull, FALSE otherwise.

pContext - is a pointer to the structure FilterContext and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

pName - is a pointer to a string containing the name of the http header to change. This argument cannot be NULL or an empty string.

pValue - is a pointer to a string containing the value for the http header.

pErrID - is a pointer to an unsigned integer where to store a status code. The status code is set to 0 if the operation is successfull, to a non zero value otherwise.

int ( AddHeader )( FilterContext pContext,
char pHheader,
unsigned int
pErrID );
This callback function allows a filter to add an http header to the list of the response http headers. Note that if the http header already exists, its value is changed to reflect the new value.

Return TRUE if successfull, FALSE otherwise.

pContext - is a pointer to the structure FilterContext and contains all the context data needed by the DSAPI layer implementation to identify which request this pertains to.

pHeader - is a pointer to a valid http header. The expected format is the same as the format of response http headers, i.e., <headerName:value>.

pErrID - is a pointer to an unsigned integer where to store a status code. The status code is set to 0 if the operation is successfull, to a non zero value otherwise. The only non zero in this case is DSAPI_INVALID_ARGUMENT which indicates that an error in the format of the supplied header has been detected.

reserved - is reserved for future use.

kFilterRawWrite Event
This event occurs when the http stack is about to send the http response data to the client. This gives a chance to the filter to change the response data that is sent to the client. This is not completly implemented in the current version of DSAPI. pEventData is a pointer to an instance of the structure FilterRawWrite and is described below:

      typedef struct {
      char* content;
      unsigned int contentLen;
      unsigned int reserved;
      } FilterRawWrite;

content - Input/Output parameter. It is a pointer to a buffer that contains the data to send to the client. The filter can change the data in place (using the same buffer) or allocate a new buffer and fill it.

contentLen - Input/Output parameter. It is the number of valid bytes in the supplied buffer on input, and/or the number of valid bytes in the buffer on output.

reserved - reserved for future use.


Running and Programming Considerations

  • A DSAPI filter is built as a shared library under UNIX and a DLL under Win32. DSAPI is supported on all Domino server platforms. The details of compiling and linking a shared library differ from platform to platform. Please refer to Chapter 3, Platform Specifics, for further information on building applications for a particular platform.
  • Since the filter is written in C, you can use the Notes C API to access Domino data or other C interfaces to access other systems.
  • A DSAPI filter is a server extension, the filter has the privileges of the server ID when accessing Domino databases through the C API.
  • Since filter notification functions may be called simultaneously from different server threads, all filter code must be thread-safe. When a Domino server thread receives an HTTP request, it allocates a new instance of the FilterContext structure. As the thread processes the request, it passes that instance to all filter functions it calls. FilterContext contains a pointer, privateContext, that you can use to store your own data structure. All thread-specific data that the filter needs to maintain from event to event should be stored in your privateContext structure.
  • You should use the AllocMem callback function to allocate dynamic memory in your filter. All memory allocated by AllocMem is automatically freed when the server thread finishes processing the request. This simplifies your filter cleanup and ensures that the memory is freed even if the thread terminates abnormally.
  • Install the filter by specifying the name of the filter in the Server record, in the field DSAPI filter file name in the Internet Protocols -> HTTP table. You can specify just the name of the filter file if it is located in the Domino program or data directories; otherwise you must specify the fully-qualified path name. Make sure that all filter files are secured by adequate file permissions and physical security, to prevent unauthorized persons from tampering with the filter.


DSAPI Sample Code

The purpose of this example is to show how to extend the Domino Web server to enable Unix password checking. When a Domino database is accessed via a Web browser, Domino can authenticate the user based on Unix password (i.e., password stored in standard Unix password registries such as /etc/passwd or NIS). It is possible to cut and paste what is documented here and incorporate it into a sample of your own. Steps for running and installing the filter are featured below.

What the sample code illustrates.

When a protected Web page is accessed, Domino will prompt for a user name and password. This example allows the user to enter a Unix password, and to be authenticated for Web access if the password can be verified. This example works only for the case where a user is known to both Domino and Unix.
The example assumes that the Unix user name is the user's Domino "short name". For instance:
Domino user name Jane Doe
Domino short name jdoe
Unix user name jdoe (note: Unix is case sensitive, so the Domino short name should be stored as lower case characters. For best interoperability, this name should be no longer than 8 characters.)

Installing and running the filter shared library.

1. Filter Installation

  • Open the Domino Name and Address book. Switch to the server view and open the server document. Edit the server document:
  • Click on the "Internet Protocols" tab.
  • Click on the "HTTP" tab.
  • Edit the field "DSAPI filter file name" to contain the name of the shared library. (If the shared library is installed to a directory other than the Domino executable directory, provide a full path name to the library).
  • Save your changes.


2. Running the filter

  • Gain access to the server console. Restart the Domino server http task (e.g., issue commands "tell http quit", "load http"). The server console should display an initialization message as the shared library is loaded.
  • From a Domino admin client, register a new Domino user, ensuring that the user's Domino short name corresponds to the desired Unix login username. Or find an existing Domino user who is already known to both Domino and Unix.
  • For the target Domino database that will be accessed from a Web browser, edit the database access control list to grant access to the Domino user.
  • Use a Web browser to access the target database. If the example is working properly, you should be prompted for user name and password. Enter the Unix password to test the example.
    Program Filter Initialization, Filter Termination and Filter Notification Definitions.

/ Input and output include files /
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/ Special dsapi include file /
#include "dsapi.h"

/ unix authentication includes /

#ifdef AIX
#include <sys/types.h>
#include <pwd.h>
#endif

/ Notes SDK include files /
#include "global.h"
#include "osmem.h"
#include "lookup.h"

/---
local procedure prototypes
/

/
Notes SDK unix shared library entrypoint /
STATUS FAR PASCAL MainEntryPoint (void);

/
Routines with syntax dictated by the DSAPI interface /
unsigned int Authenticate(FilterContext
context, FilterAuthenticate authData);

/
Retrieval of names from Notes name and address book /
int getUserNames (FilterContext
context, char userName, char pUserFullName, int  pUserFullNameLen,
                  char pUserShortName,
                  int  pUserShortNameLen);

int getLookupInfo (FilterContext
context, char *pMatch, int  itemNumber, char
pInfo, int  pInfoLen);

/
unix password check routine /
int unixAuthenticate(char
userName, char password);

/
---
local procedures follow
/

STATUS FAR PASCAL MainEntryPoint (void)
{
/
 
Description:  Provide a main entry point for the Notes API to
                initialize inside of this shared library.  We need
 
              this entry point because we want to be able to lookup
                user information in the name and address book via the
 
              Notes SDK API.
 
 
Input:  nothing
  Output: nothing
 
Return: NOERROR
 /
return NOERROR;
}

/
---
filter initialization
/
unsigned int FilterInit(FilterInitData filterInitData)
{
/

  Description:  Filter initialization is performed when the filter
 
              shared library is dynamically loaded.
 
 
Input:  filterInitData     dsapi specification controls the format
                             of data
 
Output: filterInitData     several fields are filled in
 
 
Return: kFilterHandledEvent
 /
        /
Required/
        filterInitData->appFilterVersion = kInterfaceVersion;  

/
Modify the following code to set the flags you want /
filterInitData->eventFlags =
                              kFilterAuthUser;

/
Set a short description for your filter /
strcpy(filterInitData->filterDesc,
               "Unix Authentication Filter");

        /
insert any global initialization code here...       /

/
Output sent to stdout and stderr is displayed on the
* server console, but is not written to the server log file.
/
printf("\nDSAPI Unix Authentication filter initialized\n");
return kFilterHandledEvent;
}

/
---
filter termination
/
unsigned int TerminateFilter(unsigned int reserved)
{
/
 
Description:  Filter termination is performed when the filter
                shared library is unloaded.
 

  Input:  reserved     currently unused (dsapi spec controls the
 
                     format of data)
  Output: none
 

  Return: kFilterHandledEvent
 
/
/ insert any global cleanup code here... /

printf("\nDSAPI Unix authentication filter unloaded\n");
return kFilterHandledEvent;
}


/---
filter notification handling
/
unsigned int HttpFilterProc(FilterContext
context,
unsigned int eventType, void eventData)
{
/

  Description:  This routine is called for all dsapi filter events.  
 

  Input:  reserved     currently unused (dsapi spec controls the
 
                     format of data)
  Output: none
 

  Return: kFilterNotHandled for all events that we don't customize,
 
        otherwise allow our filter routine to provide a return
          value.
 
/

/ Include only those events we want to handle /
switch (eventType) {
case kFilterAuthUser:
return Authenticate(context,
                                    (FilterAuthenticate *)eventData);
default:
break;
}

return kFilterNotHandled;
}

Filter Authentication Main Functionality which controls the authentication from both the Domino and Unix side.

/---
handle user authentication
/
unsigned int Authenticate(FilterContext
context,
                          FilterAuthenticate authData)
{
/

  Description:  This routine is called on a dsapi kFilterAuthUser
 
              event.
 
 
Input:  context     dsapi specification controls the format of data
          authData    password field contains the password to use for
 
                    authentication userName field contains the name
                      to authenticate foundInCache field is TRUE if
 
                    user has been found in the cache and can be
                      authenticated on that basis.
 

  Output: authData    authName field is filled with user's
 
                    distinguished name authType filed is filled
                      with kNotAuthentic if we can't authenticate the
 
                    unix user kAuthenticBasic if we can
                      authenticate the unix user.
 

  Return: kFilterNotHandled if we do not understand the input data,
 
                    or if the user has been found in the cache, or
                      if we find that the user to be authenticated is
 
                    not known to unix.
          kFilterHandledEvent if the user is known to unix.
 
/
/ If the user is found in the cache, then we don't need to do
* anything further.
/
if (!authData || authData->foundInCache)
return kFilterNotHandled;

/ Attempt to verify the user's password.
/
if (authData->userName && authData->password) {
char fullName = NULL;
int fullNameLen = 0;
char
shortName = NULL;
int shortNameLen = 0;

                / Lookup the user in the Name and Address book.  Get
                 
the user's short name (which we expect is the unix
                  user name), and get the user's fullname (which we
                 
expect will be in the format to pass back to
                  dsapi).
/
if (0 == getUserNames (context,
                                       (char )authData->userName,
                                       &fullName,
                                       &fullNameLen,
                                       &shortName,
                                       &shortNameLen) ) {
int unixauth;
                        /
Do the unix authentication. The
                          unixAuthenticate routine returns: -1 on
                         
error, 0 on success, 1 if user is not known
                          to unix.
/
unixauth = unixAuthenticate(shortName,
                                          (char )authData->password);
/
Return if user is not known to unix /
if (1 == unixauth) {
printf("\nUser name not in UNIX system.\n")
return kFilterNotHandled;
}
/
Copy the canonical name for this user that
                          dsapi requires.
                         
/
strncpy ((char )authData->authName, fullName,
                                 authData->authNameSize);

/
Fill in authType return info that dsapi
                          requires.
                         
/
if (unixauth) {
/ The unixauthenticate routine
                                 
returned error:  we couldn't
* authenticate with the input
                                  password.
/
authData->authType = kNotAuthentic;
} else {
/ For debug purposes, write to the
                                 
Domino console that authentication
                                  with the input password succeeded.
* You may wish to remove this printf.
/
printf("DSAPI Filter authenticated %s as %s (unix user %s)\n",
                                       (char *)authData->userName,
                                       authData->authName, shortName);
authData->authType = kAuthenticBasic;
}
return kFilterHandledEvent;
}
}
return kFilterNotHandled;
}

Actual routines to lookup the user from the Domino side.

Each time this filter's Authenticate routine is called, a lookup will be done of the user in the Domino name and address book (assuming that the user is not found in the cache from a previous authentication). This lookup will attempt to retrieve the user's Domino short name (e.g., jdoe) and the user's full Domino name. If unix user names do not correspond to Domino short names, this example would need to be changed to handle the way in which unix names should be mapped to Domino names, and vice versa.

int getUserNames (FilterContext context,
                  char
userName,
                  char pUserFullName,
                  int  *pUserFullNameLen,
                  char
pUserShortName,
                  int  pUserShortNameLen) {
/

  Description:  Lookup the user and return the user's full name and
 
              short name.
 
 
Input:  context            context we'll use for allocating memory
          userName           the name of the user to lookup
 
Output: pUserFullName      location of the user's full name
          pUserFullNameLen   location to store the length of fullname
 
        pUserShortName     location of the user's shortname
          pUserShortNameLen  location to store the length of
 
                           shortname
 
 
Return: -1 on error, 0 on success
 /
STATUS error = NOERROR;
HANDLE hLookup = NULLHANDLE;
WORD Matches = 0;
char
pLookup;
char pName = NULL;
char
pMatch = NULL;
        int     rc = -1;

if (!userName || !pUserFullName || !pUserFullNameLen ||
            !pUserShortName || !pUserShortNameLen)
return rc;

/ Initialize output /
pUserFullName = NULL;
pUserFullNameLen = 0;
pUserShortName = NULL;
pUserShortNameLen = 0;

/ do the name lookup
/
error = NAMELookup(NULL, / NULL means look locally /
                           0,   / flags /
                           1,   / number of namespaces /
                           "$Users", / namespace list /
                           1,   / number of names to lookup /
                           userName, / list of names to lookup /
                           2, / number of items to return /
                           "FullName\0ShortName", / list of items to
                                                   
return /
                           &hLookup); /
place to receive handle of
                                        return buffer /

if (error || (NULLHANDLE == hLookup))
goto NoUnlockExit;

pLookup = (char ) OSLockObject(hLookup);

/
Get a pointer to our entry.
/
pName = (char
)NAMELocateNextName(pLookup, / name lookup
                                                     
buffer /
                                        NULL, /
start at beginning of
                                                lookup buffer /
&Matches); / Receives number
                                                    * of times we
                                                    * found the entry
                                                    * (should be 1)
                                                   
/

/ If we didn't find the entry, then quit /
if ((pName == NULL) || (Matches <= 0)) {
goto Exit;
}

pMatch = (char )NAMELocateNextMatch(pLookup,  / name lookup
                                                        * buffer /
                                      pName, /
entry that we found /
                                      NULL); /
no previous match /
if (NULL == pMatch) {
goto Exit;
}
/
Get the full name from the info we got back /
if ( getLookupInfo (context,
                            pMatch,
                            0,
                            pUserFullName,
                            pUserFullNameLen) )
goto Exit;

/
Get the short name from the info we got back /
if ( getLookupInfo (context,
                            pMatch,
                            1,
                            pUserShortName,
                            pUserShortNameLen) )
goto Exit;
else
/
Success in all things /
rc = 0;

Exit:
if ( pLookup && hLookup )
OSUnlock(hLookup);
NoUnlockExit:
if (NULLHANDLE != hLookup)
OSMemFree(hLookup);
return rc;
}

int getLookupInfo (FilterContext
context,
                   char pMatch,
                   int  itemNumber,
                   char
pInfo,
                   int  
pInfoLen) {
/
 
Description:  Get the info from the lookup buffer
 
 
Input:  context            context we'll use for allocating memory
          pMatch             the name of the lookup buffer
 
        itemNumber         where the info is stored in the lookup
                             buffer
 
Output: pInfo              location of the info buffer
          pInfoLen           location to store the info length
 

  Return: -1 on error, 0 on success
 
/

unsigned int reserved = 0;
unsigned int errID;
char ValuePtr = NULL;
WORD ValueLength, DataType;
STATUS error;
void
newSpace = NULL;

if (!pMatch || !pInfo || !pInfoLen || (itemNumber < 0))
return -1;

/ Initialize output /
pInfo = NULL;
pInfoLen = 0;

/ Check the type and length of the info /
ValuePtr = (char )NAMELocateItem(pMatch, / match that we
                                                    found /
                                    itemNumber, / item # in order
                                                 
of item on lookup /
                                    &DataType, /
return the datatype
                                                * of item value /
                                    &ValueLength); /
size of rtn
                                                    * value /
if (NULL == ValuePtr || ValueLength == 0) {
/
there is no info /
return -1;
}
ValueLength -= sizeof(WORD); /
remove datatype word included
                                      * in the list length
                                      /
  /
check the value DataType /
switch (DataType) {
case TYPE_TEXT_LIST:
break;

case TYPE_TEXT:
break;

default:
return -1;
}

/
Allocate space for the info.  This memory will be freed
* automatically when the thread terminates.
/
newSpace = (context->AllocMem)(context, ValueLength+1,
                                       reserved, &errID);
pInfo = (char ) newSpace;
if (NULL ==
pInfo) {
printf ("Out of memory\n");
return -1;
}

/ Get the info /
error = NAMEGetTextItem(pMatch, / match that we found /
                                itemNumber, / item # in order of item
                                             
on lookup /
                                0, /
Member # of item in text
                                    * lists /
pInfo, / buffer to copy result
                                         
into /
ValueLength+1); /
Length of buffer /
if (!error) {
pInfoLen = ValueLength +1;
return 0;
}
return -1;
}

Authenticate the user from the Unix side.


int unixAuthenticate(char userName, char password) {
/
 
Description:  See if the user is known to unix, and if so, check
                that the password can be verified.
 

  Input:  userName           unix user name
 
        password           unix password
 
 
Return: -1 on error, 0 on success, 1 if user is not known to unix
 /
char buffer[1024];
int error = -1;
int success = 0;
int unknown = 1;

#ifdef AIX
struct passwd
result;
#endif

printf("\nUserName = %s\n", userName );
if (!userName)
{
printf("\nUserName = %s\n",
userName );
return error;
}


/ Get the unix record for this user /

#ifdef AIX
result = getpwnam(userName);
if (result && result->pw_passwd) {
                / Encrypt the password and see if it matches the
                 
encrypted password from the user's record.
/
char
thisCrypt = NULL;
thisCrypt = (char )crypt(password,
                                          result->pw_passwd);
if (strcmp (result->pw_passwd, thisCrypt) == 0) {
return success;
} else {
return error;
}
}
#endif
return unknown;
}

/
----- end of dsapifilter.c */