CASA/CASA-auth-token/server/AuthTokenValidate/idenTokenProviders/casa/identoken.c
2007-02-16 18:36:27 +00:00

1471 lines
46 KiB
C

/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
//===[ Include files ]=====================================================
#include "internal.h"
//===[ Type definitions ]==================================================
//
// XML Constants for the CASA Identity Token
//
#define CASA_IDENT_TOKEN_ELEMENT_NAME "casa_ident_tok"
#define ID_ELEMENT_NAME "id"
#define SOURCE_NAME_ELEMENT_NAME "source_name"
#define SOURCE_URL_ELEMENT_NAME "source_url"
#define TARGET_SERVICE_ELEMENT_NAME "target_service"
#define TARGET_HOST_ELEMENT_NAME "target_host"
#define ATTRIBUTES_ELEMENT_NAME "attributes"
//
// Parse states
//
#define AWAITING_ROOT_ELEMENT_START 0x0
#define AWAITING_ROOT_ELEMENT_END 0x1
#define AWAITING_ID_DATA 0x2
#define AWAITING_ID_ELEMENT_START 0x3
#define AWAITING_ID_ELEMENT_END 0x4
#define AWAITING_SOURCE_NAME_DATA 0x5
#define AWAITING_SOURCE_NAME_ELEMENT_START 0x6
#define AWAITING_SOURCE_NAME_ELEMENT_END 0x7
#define AWAITING_SOURCE_URL_DATA 0x8
#define AWAITING_SOURCE_URL_ELEMENT_START 0x9
#define AWAITING_SOURCE_URL_ELEMENT_END 0xA
#define AWAITING_TARGET_SERVICE_DATA 0xB
#define AWAITING_TARGET_SERVICE_ELEMENT_START 0xC
#define AWAITING_TARGET_SERVICE_ELEMENT_END 0xD
#define AWAITING_TARGET_HOST_DATA 0xE
#define AWAITING_TARGET_HOST_ELEMENT_START 0xF
#define AWAITING_TARGET_HOST_ELEMENT_END 0x10
#define AWAITING_ATTRIBUTES_ELEMENT_START 0x11
#define AWAITING_ATTRIBUTE_DATA 0x12
#define AWAITING_ATTRIBUTE_START 0x13
#define AWAITING_ATTRIBUTE_END 0x14
#define DONE_PARSING 0x15
//
// Attribute structure
//
typedef struct _Attribute
{
LIST_ENTRY listEntry;
char *pAttribName;
size_t attribNameLen;
char *pAttribValue;
size_t attribValueLen;
} Attribute, *PAttribute;
//
// Identity Token Interface instance data
//
typedef struct _IdenTokenIfInstance
{
int refCount;
char *pIdentId;
size_t identIdLen;
char *pIdentSourceName;
size_t identSourceNameLen;
char *pIdentSourceUrl;
size_t identSourceUrlLen;
char *pTargetService;
size_t targetServiceLen;
char *pTargetHost;
size_t targetHostLen;
LIST_ENTRY attributeListHead;
IdenTokenIf idenTokenIf;
} IdenTokenIfInstance, *PIdenTokenIfInstance;
//
// Identity Token Parse Structure
//
typedef struct _IdenTokenParse
{
XML_Parser p;
int state;
size_t elementDataProcessed;
IdenTokenIfInstance *pIdenTokenIfInstance;
CasaStatus status;
} IdenTokenParse, *PIdenTokenParse;
//===[ Function prototypes ]===============================================
//===[ Global variables ]==================================================
// IdenTokenIf variables
static
int g_numIdenTokenIfObjs = 0;
// Synchronization mutex
static
HANDLE g_idenTokenIfMutex = NULL;
//++=======================================================================
static
void
FreeIdenTokenIfInstance(
IN IdenTokenIfInstance *pIdenTokenIfInstance)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
LIST_ENTRY *pListEntry;
DbgTrace(2, "-FreeIdenTokenIfInstance- Start\n", 0);
// Free all of the resources associated with the IdenTokenIfInstance
if (pIdenTokenIfInstance->pIdentId)
free(pIdenTokenIfInstance->pIdentId);
if (pIdenTokenIfInstance->pIdentSourceName)
free(pIdenTokenIfInstance->pIdentSourceName);
if (pIdenTokenIfInstance->pIdentSourceUrl)
free(pIdenTokenIfInstance->pIdentSourceUrl);
if (pIdenTokenIfInstance->pTargetService)
free(pIdenTokenIfInstance->pTargetService);
if (pIdenTokenIfInstance->pTargetHost)
free(pIdenTokenIfInstance->pTargetHost);
// Go through all of the associated attributes
pListEntry = pIdenTokenIfInstance->attributeListHead.Flink;
while (pListEntry != &pIdenTokenIfInstance->attributeListHead)
{
Attribute *pAttribute = CONTAINING_RECORD(pListEntry, Attribute, listEntry);
// Free resources associated with the attribute
if (pAttribute->pAttribName)
free(pAttribute->pAttribName);
if (pAttribute->pAttribValue)
free(pAttribute->pAttribValue);
// Forget about this attribute
RemoveEntryList(&pAttribute->listEntry);
free(pAttribute);
// Start from the top again
pListEntry = pIdenTokenIfInstance->attributeListHead.Flink;
}
// Free the identity token if instance structure
free(pIdenTokenIfInstance);
DbgTrace(2, "-FreeIdenTokenIfInstance- End\n", 0);
}
//++=======================================================================
static
void XMLCALL
IdenTokenStartElementHandler(
IN void *pUserData,
IN const XML_Char *name,
IN const XML_Char **atts)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
IdenTokenParse *pIdenTokenParse = (IdenTokenParse*) pUserData;
Attribute *pAttribute;
DbgTrace(2, "-IdenTokenStartElementHandler- Start\n", 0);
// Proceed based on the state
switch (pIdenTokenParse->state)
{
case AWAITING_ROOT_ELEMENT_START:
// In this state, we are only expecting the CASA Identity
// Token Element.
if (strcmp(name, CASA_IDENT_TOKEN_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_ID_ELEMENT_START;
}
else
{
DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_ID_ELEMENT_START:
// In this state, we are only expecting the ID Element.
if (strcmp(name, ID_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_ID_DATA;
}
else
{
DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_SOURCE_NAME_ELEMENT_START:
// In this state, we are only expecting the Source Name Element.
if (strcmp(name, SOURCE_NAME_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_SOURCE_NAME_DATA;
}
else
{
DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_SOURCE_URL_ELEMENT_START:
// In this state, we are only expecting the Source Url Element.
if (strcmp(name, SOURCE_URL_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_SOURCE_URL_DATA;
}
else
{
DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_TARGET_SERVICE_ELEMENT_START:
// In this state, we are only expecting the Target Service Element.
if (strcmp(name, TARGET_SERVICE_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_TARGET_SERVICE_DATA;
}
else
{
DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_TARGET_HOST_ELEMENT_START:
// In this state, we are only expecting the Target Host Element.
if (strcmp(name, TARGET_HOST_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_TARGET_HOST_DATA;
}
else
{
DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_ATTRIBUTES_ELEMENT_START:
// In this state, we are only expecting the Attributes Element.
if (strcmp(name, ATTRIBUTES_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_ATTRIBUTE_START;
}
else
{
DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected start element\n", 0);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_ATTRIBUTE_START:
// Allocate an initialize Attribute structure
pAttribute = malloc(sizeof(*pAttribute));
if (pAttribute)
{
memset(pAttribute, 0, sizeof(*pAttribute));
InsertTailList(&pIdenTokenParse->pIdenTokenIfInstance->attributeListHead,
&pAttribute->listEntry);
// Now save the attribute name
pAttribute->attribNameLen = strlen(name) + 1;
pAttribute->pAttribName = malloc(pAttribute->attribNameLen);
if (pAttribute->pAttribName)
{
strcpy(pAttribute->pAttribName, name);
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_ATTRIBUTE_DATA;
}
else
{
DbgTrace(0, "-IdenTokenStartElementHandler- Buffer allocation failure\n", 0);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
}
else
{
DbgTrace(0, "-IdenTokenStartElementHandler- Buffer allocation failure\n", 0);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
default:
DbgTrace(0, "-IdenTokenStartElementHandler- Un-expected state = %d\n", pIdenTokenParse->state);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
break;
}
DbgTrace(2, "-IdenTokenStartElementHandler- End\n", 0);
}
//++=======================================================================
static
CasaStatus
ConsumeElementData(
IN IdenTokenParse *pIdenTokenParse,
IN const XML_Char *s,
IN int len,
INOUT char **ppElementData,
INOUT size_t *pElementDataLen)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
CasaStatus retStatus = CASA_STATUS_SUCCESS;
DbgTrace(3, "-ConsumeElementData- Start\n", 0);
// Proceed based on whether or not we have already consumed data
// for this element.
if (*ppElementData == NULL)
{
// We have not yet consumed data for this element
pIdenTokenParse->elementDataProcessed = len;
// Allocate a buffer to hold this element data (null terminated).
*ppElementData = (char*) malloc(len + 1);
if (*ppElementData)
{
memset(*ppElementData, 0, len + 1);
memcpy(*ppElementData, s, len);
// Return the length of the element data buffer
*pElementDataLen = pIdenTokenParse->elementDataProcessed + 1;
}
else
{
DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
}
else
{
char *pNewBuf;
// We have already received token data, append this data to it.
pNewBuf = (char*) malloc((size_t)(pIdenTokenParse->elementDataProcessed + len + 1));
if (pNewBuf)
{
memset(pNewBuf,
0,
pIdenTokenParse->elementDataProcessed + len + 1);
memcpy(pNewBuf,
*ppElementData,
pIdenTokenParse->elementDataProcessed);
memcpy(pNewBuf + pIdenTokenParse->elementDataProcessed, s, len);
pIdenTokenParse->elementDataProcessed += len;
// Swap the buffers
free(*ppElementData);
*ppElementData = pNewBuf;
// Return the length of the element data buffer
*pElementDataLen = pIdenTokenParse->elementDataProcessed + 1;
}
else
{
DbgTrace(0, "-ConsumeElementData- Buffer allocation failure\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
}
DbgTrace(3, "-ConsumeElementData- End, retStatus = %0X\n", retStatus);
return retStatus;
}
//++=======================================================================
static
void XMLCALL
IdenTokenCharDataHandler(
IN void *pUserData,
IN const XML_Char *s,
IN int len)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
IdenTokenParse *pIdenTokenParse = (IdenTokenParse*) pUserData;
Attribute *pAttribute;
DbgTrace(2, "-IdenTokenCharDataHandler- Start\n", 0);
// Just exit if being called to process LF and CR characters
if (len == 1
&& ((*s == '\n') || (*s == '\r')))
{
goto exit;
}
// Proceed based on the state
switch (pIdenTokenParse->state)
{
case AWAITING_ID_DATA:
case AWAITING_ID_ELEMENT_END:
pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse,
s,
len,
&pIdenTokenParse->pIdenTokenIfInstance->pIdentId,
&pIdenTokenParse->pIdenTokenIfInstance->identIdLen);
if (CASA_SUCCESS(pIdenTokenParse->status))
{
// Advanced to the next state
pIdenTokenParse->state = AWAITING_ID_ELEMENT_END;
}
else
{
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_SOURCE_NAME_DATA:
case AWAITING_SOURCE_NAME_ELEMENT_END:
pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse,
s,
len,
&pIdenTokenParse->pIdenTokenIfInstance->pIdentSourceName,
&pIdenTokenParse->pIdenTokenIfInstance->identSourceNameLen);
if (CASA_SUCCESS(pIdenTokenParse->status))
{
// Advanced to the next state
pIdenTokenParse->state = AWAITING_SOURCE_NAME_ELEMENT_END;
}
else
{
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_SOURCE_URL_DATA:
case AWAITING_SOURCE_URL_ELEMENT_END:
pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse,
s,
len,
&pIdenTokenParse->pIdenTokenIfInstance->pIdentSourceUrl,
&pIdenTokenParse->pIdenTokenIfInstance->identSourceUrlLen);
if (CASA_SUCCESS(pIdenTokenParse->status))
{
// Advanced to the next state
pIdenTokenParse->state = AWAITING_SOURCE_URL_ELEMENT_END;
}
else
{
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_TARGET_SERVICE_DATA:
case AWAITING_TARGET_SERVICE_ELEMENT_END:
pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse,
s,
len,
&pIdenTokenParse->pIdenTokenIfInstance->pTargetService,
&pIdenTokenParse->pIdenTokenIfInstance->targetServiceLen);
if (CASA_SUCCESS(pIdenTokenParse->status))
{
// Advanced to the next state
pIdenTokenParse->state = AWAITING_TARGET_SERVICE_ELEMENT_END;
}
else
{
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_TARGET_HOST_DATA:
case AWAITING_TARGET_HOST_ELEMENT_END:
pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse,
s,
len,
&pIdenTokenParse->pIdenTokenIfInstance->pTargetHost,
&pIdenTokenParse->pIdenTokenIfInstance->targetHostLen);
if (CASA_SUCCESS(pIdenTokenParse->status))
{
// Advanced to the next state
pIdenTokenParse->state = AWAITING_TARGET_HOST_ELEMENT_END;
}
else
{
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_ATTRIBUTE_DATA:
case AWAITING_ATTRIBUTE_END:
// Get a pointer to current attribute structure
pAttribute = CONTAINING_RECORD(pIdenTokenParse->pIdenTokenIfInstance->attributeListHead.Blink,
Attribute,
listEntry);
pIdenTokenParse->status = ConsumeElementData(pIdenTokenParse,
s,
len,
&pAttribute->pAttribValue,
&pAttribute->attribValueLen);
if (CASA_SUCCESS(pIdenTokenParse->status))
{
// Advanced to the next state
pIdenTokenParse->state = AWAITING_ATTRIBUTE_END;
}
else
{
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
default:
DbgTrace(0, "-IdenTokenCharDataHandler- Un-expected state = %d\n", pIdenTokenParse->state);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
break;
}
exit:
DbgTrace(2, "-IdenTokenCharDataHandler- End\n", 0);
}
//++=======================================================================
static
void XMLCALL
IdenTokenEndElementHandler(
IN void *pUserData,
IN const XML_Char *name)
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
IdenTokenParse *pIdenTokenParse = (IdenTokenParse*) pUserData;
DbgTrace(2, "-IdenTokenEndElementHandler- Start\n", 0);
// Proceed based on the state
switch (pIdenTokenParse->state)
{
case AWAITING_ROOT_ELEMENT_END:
// In this state, we are only expecting the CASA Identity
// Token Element.
if (strcmp(name, CASA_IDENT_TOKEN_ELEMENT_NAME) == 0)
{
// Done.
pIdenTokenParse->state = DONE_PARSING;
}
else
{
DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_ID_ELEMENT_END:
// In this state, we are only expecting the Id Element.
if (strcmp(name, ID_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_SOURCE_NAME_ELEMENT_START;
}
else
{
DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_SOURCE_NAME_ELEMENT_END:
// In this state, we are only expecting the Source Name Element.
if (strcmp(name, SOURCE_NAME_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_SOURCE_URL_ELEMENT_START;
}
else
{
DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_SOURCE_URL_ELEMENT_END:
// In this state, we are only expecting the Source URL Element.
if (strcmp(name, SOURCE_URL_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_TARGET_SERVICE_ELEMENT_START;
}
else
{
DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_TARGET_SERVICE_ELEMENT_END:
// In this state, we are only expecting the Target Service Element.
if (strcmp(name, TARGET_SERVICE_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_TARGET_HOST_ELEMENT_START;
}
else
{
DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_TARGET_HOST_ELEMENT_END:
// In this state, we are only expecting the Target Host Element.
if (strcmp(name, TARGET_HOST_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_ATTRIBUTES_ELEMENT_START;
}
else
{
DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
case AWAITING_ATTRIBUTE_END:
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_ATTRIBUTE_START;
break;
case AWAITING_ATTRIBUTE_START:
// We should we done with the attributes, in this state we are only expecting
// the Attributes element.
if (strcmp(name, ATTRIBUTES_ELEMENT_NAME) == 0)
{
// Good, advance to the next state.
pIdenTokenParse->state = AWAITING_ROOT_ELEMENT_END;
}
else
{
DbgTrace(0, "-IdenTokenEndHandler- Un-expected end element, state = %08x\n", pIdenTokenParse->state);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
}
break;
default:
DbgTrace(0, "-IdenTokenEndElementHandler- Un-expected state = %d\n", pIdenTokenParse->state);
XML_StopParser(pIdenTokenParse->p, XML_FALSE);
break;
}
DbgTrace(2, "-IdenTokenEndElementHandler- End\n", 0);
}
//++=======================================================================
static
int SSCS_CALL
AddReference(
IN const void *pIfInstance)
//
// Arguments:
// pIfInstance -
// Pointer to interface object.
//
// Returns:
// Interface reference count.
//
// Description:
// Increases interface reference count.
//
// L2
//=======================================================================--
{
int refCount;
IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf);
DbgTrace(2, "-AddReference- Start\n", 0);
// Increment the reference count on the object
PlatAcquireMutex(g_idenTokenIfMutex);
pIdenTokenIfInstance->refCount ++;
refCount = pIdenTokenIfInstance->refCount;
PlatReleaseMutex(g_idenTokenIfMutex);
DbgTrace(2, "-AddReference- End, refCount = %0X\n", refCount);
return refCount;
}
//++=======================================================================
static
void SSCS_CALL
ReleaseReference(
IN const void *pIfInstance)
//
// Arguments:
// pIfInstance -
// Pointer to interface object.
//
// Returns:
// Nothing.
//
// Description:
// Decreases interface reference count. The interface is deallocated if
// the reference count becomes zero.
//
// L2
//=======================================================================--
{
bool freeObj = false;
IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf);
DbgTrace(2, "-ReleaseReference- Start\n", 0);
// Decrement the reference count on the object and determine if it needs to
// be released.
PlatAcquireMutex(g_idenTokenIfMutex);
pIdenTokenIfInstance->refCount --;
if (pIdenTokenIfInstance->refCount == 0)
{
// The object needs to be released, forget about it.
freeObj = true;
g_numIdenTokenIfObjs --;
}
PlatReleaseMutex(g_idenTokenIfMutex);
// Free object if necessary
if (freeObj)
{
FreeIdenTokenIfInstance(pIdenTokenIfInstance);
}
DbgTrace(2, "-ReleaseReference- End\n", 0);
}
//++=======================================================================
static
CasaStatus SSCS_CALL
GetIdentityId(
IN const void *pIfInstance,
INOUT char *pIdentIdBuf,
INOUT size_t *pIdentIdLen)
//
// Arguments:
// pIfInstance -
// Pointer to interface object.
//
// pIdentIdBuf -
// Pointer to buffer that will receive the identity id. The returned
// id will be in the form of a NULL terminated string.
//
// pIdentIdBufLen -
// Pointer to variable with the length of the buffer pointed by
// pIdentIdBuf. On exit it contains the length of the returned id
// (including the NULL terminator).
//
//
// Returns:
// Casa Status
//
// Description:
// Get the identity id associated with the identity token.
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf);
DbgTrace(2, "-GetIdentityId- Start\n", 0);
// Check the input parameters
if (pIfInstance == NULL
|| pIdentIdLen == NULL
|| (pIdentIdBuf == NULL && *pIdentIdLen != 0))
{
DbgTrace(0, "-GetIdentityId- Invalid parameter\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INVALID_PARAMETER);
goto exit;
}
// Determine if the caller's buffer is large enough
if (*pIdentIdLen >= pIdenTokenIfInstance->identIdLen)
{
// Return the data to the caller
memcpy(pIdentIdBuf, pIdenTokenIfInstance->pIdentId, pIdenTokenIfInstance->identIdLen);
// Success
retStatus = CASA_STATUS_SUCCESS;
}
else
{
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_BUFFER_OVERFLOW);
}
// Return the lenght of the id
*pIdentIdLen = pIdenTokenIfInstance->identIdLen;
exit:
DbgTrace(2, "-GetIdentityId- End, retStatus = %0X\n", retStatus);
return retStatus;
}
//++=======================================================================
static
CasaStatus SSCS_CALL
GetSourceName(
IN const void *pIfInstance,
INOUT char *pSourceNameBuf,
INOUT size_t *pSourceNameLen)
//
// Arguments:
// pIfInstance -
// Pointer to interface object.
//
// pSourceNameBuf -
// Pointer to buffer that will receive the name associated with the
// identity information source. The returned name will be in the form
// of a NULL terminated string.
//
// pSourceNameBufLen -
// Pointer to variable with the length of the buffer pointed by
// pSourceNameBuf. On exit it contains the length of the returned
// name (including the NULL terminator).
//
//
// Returns:
// Casa Status
//
// Description:
// Get the name of the identity source associated with the identity token.
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf);
DbgTrace(2, "-GetSourceName- Start\n", 0);
// Check the input parameters
if (pIfInstance == NULL
|| pSourceNameLen == NULL
|| (pSourceNameBuf == NULL && *pSourceNameLen != 0))
{
DbgTrace(0, "-GetSourceName- Invalid parameter\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INVALID_PARAMETER);
goto exit;
}
// Determine if the caller's buffer is large enough
if (*pSourceNameLen >= pIdenTokenIfInstance->identSourceNameLen)
{
// Return the data to the caller
memcpy(pSourceNameBuf, pIdenTokenIfInstance->pIdentSourceName, pIdenTokenIfInstance->identSourceNameLen);
// Success
retStatus = CASA_STATUS_SUCCESS;
}
else
{
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_BUFFER_OVERFLOW);
}
// Return the lenght of the source name
*pSourceNameLen = pIdenTokenIfInstance->identSourceNameLen;
exit:
DbgTrace(2, "-GetSourceName- End, retStatus = %0X\n", retStatus);
return retStatus;
}
//++=======================================================================
static
CasaStatus SSCS_CALL
GetSourceUrl(
IN const void *pIfInstance,
INOUT char *pSourceUrlBuf,
INOUT size_t *pSourceUrlLen)
//
// Arguments:
// pIfInstance -
// Pointer to interface object.
//
// pSourceUrlBuf -
// Pointer to buffer that will receive the URL associated with the
// identity information source. The returned URL will be in the form
// of a NULL terminated string.
//
// pSourceUrlBufLen -
// Pointer to variable with the length of the buffer pointed by
// pSourceUrlBuf. On exit it contains the length of the returned
// URL (including the NULL terminator).
//
//
// Returns:
// Casa Status
//
// Description:
// Get the URL to the identity source associated with the identity token.
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf);
DbgTrace(2, "-GetSourceUrl- Start\n", 0);
// Check the input parameters
if (pIfInstance == NULL
|| pSourceUrlLen == NULL
|| (pSourceUrlBuf == NULL && *pSourceUrlLen != 0))
{
DbgTrace(0, "-GetSourceUrl- Invalid parameter\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INVALID_PARAMETER);
goto exit;
}
// Determine if the caller's buffer is large enough
if (*pSourceUrlLen >= pIdenTokenIfInstance->identSourceUrlLen)
{
// Return the data to the caller
memcpy(pSourceUrlBuf, pIdenTokenIfInstance->pIdentSourceUrl, pIdenTokenIfInstance->identSourceUrlLen);
// Success
retStatus = CASA_STATUS_SUCCESS;
}
else
{
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_BUFFER_OVERFLOW);
}
// Return the lenght of the source url
*pSourceUrlLen = pIdenTokenIfInstance->identSourceUrlLen;
exit:
DbgTrace(2, "-GetSourceUrl- End, retStatus = %0X\n", retStatus);
return retStatus;
}
//++=======================================================================
static
CasaStatus SSCS_CALL
AttributeEnumerate(
IN const void *pIfInstance,
INOUT unsigned int *pEnumHandle,
INOUT char *pAttribNameBuf,
INOUT size_t *pAttribNameLen,
INOUT char *pAttribValueBuf,
INOUT size_t *pAttribValueLen)
//
// Arguments:
// pIfInstance -
// Pointer to interface object.
//
// pEnumHandle -
// Pointer to enumeration handle. Must be set to 0 to start an
// enumeration. Note the enumeration handle advances if the
// function returns success.
//
// pAttribNameBuf -
// Pointer to buffer that will receive the identity attribute name. The
// returned name will be in the form of a NULL terminated string.
//
// pAttribNameLen -
// Pointer to variable with the length of the buffer pointed by
// pAttribNameBuf. On exit it contains the length of the returned
// name (including the NULL terminator).
//
// pAttribValueBuf -
// Pointer to buffer that will receive the identity attribute value. The
// returned value will be in the form of a NULL terminated string.
//
// pAttribValueLen -
// Pointer to variable with the length of the buffer pointed by
// pAttribValueBuf. On exit it contains the length of the returned
// value (including the NULL terminator).
//
//
// Returns:
// Casa Status
//
// Description:
// Enumerates through the attributes associated with the identity token.
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
IdenTokenIfInstance *pIdenTokenIfInstance = CONTAINING_RECORD(pIfInstance, IdenTokenIfInstance, idenTokenIf);
LIST_ENTRY *pListEntry;
int i;
Attribute *pAttribute;
DbgTrace(2, "-AttributeEnumerate- Start\n", 0);
// Check the input parameters
if (pIfInstance == NULL
|| pEnumHandle == NULL
|| pAttribNameLen == NULL
|| pAttribValueLen == NULL
|| (pAttribNameBuf == NULL && *pAttribNameLen != 0)
|| (pAttribValueBuf == NULL && *pAttribValueLen != 0))
{
DbgTrace(0, "-AttributeEnumerate- Invalid parameter\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INVALID_PARAMETER);
goto exit;
}
// Find the appropriate attribute based on the enum handle which is used as
// an index.
i = 0;
pAttribute = NULL;
pListEntry = pIdenTokenIfInstance->attributeListHead.Flink;
while (pListEntry != &pIdenTokenIfInstance->attributeListHead)
{
// Is this the attribute needed
if (i == *pEnumHandle)
{
// This is the attribute needed
pAttribute = CONTAINING_RECORD(pListEntry, Attribute, listEntry);
break;
}
else
{
// No, try the next one.
pListEntry = pListEntry->Flink;
i++;
}
}
// Check if we found an attribute for the indicated enum handle
if (pAttribute)
{
// Try to return the attribute name
if (*pAttribNameLen >= pAttribute->attribNameLen)
{
// Return the attribute name
memcpy(pAttribNameBuf, pAttribute->pAttribName, pAttribute->attribNameLen);
// Now, try to return the attribute value
if (*pAttribValueLen >= pAttribute->attribValueLen)
{
// Return the attribute value
memcpy(pAttribValueBuf, pAttribute->pAttribValue, pAttribute->attribValueLen);
// Success
retStatus = CASA_STATUS_SUCCESS;
// Advance the enum handle
*pEnumHandle = *pEnumHandle + 1;
}
else
{
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_BUFFER_OVERFLOW);
}
}
else
{
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_BUFFER_OVERFLOW);
}
// Return the attribute lengths
*pAttribNameLen = pAttribute->attribNameLen;
*pAttribValueLen = pAttribute->attribValueLen;
}
else
{
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_NO_MORE_ENTRIES);
}
exit:
DbgTrace(2, "-AttributeEnumerate- End, retStatus = %0X\n", retStatus);
return retStatus;
}
//++=======================================================================
CasaStatus
GetIdenTokenInterface(
IN const char *pTokenBuf,
IN const uint32_t tokenLen,
INOUT IdenTokenIf **ppIdenTokenIf)
//
// Arguments:
//
// Returns:
// Casa Status
//
// Description:
// Get principal interface instanced for the identity associated
// with specified identity token.
//
// L2
//=======================================================================--
{
IdenTokenIfInstance *pIdenTokenIfInstance;
CasaStatus retStatus;
DbgTrace(2, "-GetIdenTokenInterface- Start\n", 0);
// Verify that the token is not too large for the parser
if (tokenLen > INT32_MAX)
{
DbgTrace(0, "-GetIdenTokenInterface- Token too large\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
goto exit;
}
// Create a IdenTokenIfInstance object for it.
pIdenTokenIfInstance = malloc(sizeof(*pIdenTokenIfInstance));
if (pIdenTokenIfInstance)
{
XML_Parser p;
IdenTokenParse idenTokenParse = {0};
/*
* CASA identity tokens have the following format:
*
* <?xml version="1.0" encoding="ISO-8859-1"?>
* <casa_ident_tok>
* <id>identity id</id>
* <source_name>identity data source name</source_name>
* <source_url>identity data source url</source_url>
* <target_service>target service name</target_service>
* <target_host>target host name</target_host>
* <attributes>
* <attribute name> attribute value</attribute name>
* <attribute2 name> attribute value</attribute2 name>
* ...
* </attributes>
* </casa_ident_tok>
*
*/
// Initialize the IdentTokenIfInstance object and set it in the
// idenTokenParse object.
memset(pIdenTokenIfInstance, 0, sizeof(*pIdenTokenIfInstance));
InitializeListHead(&pIdenTokenIfInstance->attributeListHead);
pIdenTokenIfInstance->idenTokenIf.addReference = AddReference;
pIdenTokenIfInstance->idenTokenIf.releaseReference = ReleaseReference;
pIdenTokenIfInstance->idenTokenIf.getIdentityId = GetIdentityId;
pIdenTokenIfInstance->idenTokenIf.getSourceName = GetSourceName;
pIdenTokenIfInstance->idenTokenIf.getSourceUrl = GetSourceUrl;
pIdenTokenIfInstance->idenTokenIf.attributeEnumerate = AttributeEnumerate;
idenTokenParse.pIdenTokenIfInstance = pIdenTokenIfInstance;
// Create parser
p = XML_ParserCreate(NULL);
if (p)
{
// Keep track of the parser in our parse object
idenTokenParse.p = p;
// Initialize the status within the parse object
idenTokenParse.status = CASA_STATUS_SUCCESS;
// Set the start and end element handlers
XML_SetElementHandler(p,
IdenTokenStartElementHandler,
IdenTokenEndElementHandler);
// Set the character data handler
XML_SetCharacterDataHandler(p, IdenTokenCharDataHandler);
// Set our user data
XML_SetUserData(p, &idenTokenParse);
// Parse the document
if (XML_Parse(p, pTokenBuf, (int) tokenLen, 1) == XML_STATUS_OK)
{
// Verify that the parse operation completed successfully
if (idenTokenParse.state == DONE_PARSING)
{
// The parse operation succeded.
retStatus = CASA_STATUS_SUCCESS;
}
else
{
DbgTrace(0, "-GetIdenTokenInterface- Parse operation did not complete\n", 0);
// Check if a status has been recorded
if (idenTokenParse.status != CASA_STATUS_SUCCESS)
{
retStatus = idenTokenParse.status;
}
else
{
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_PROTOCOL_ERROR);
}
}
}
else
{
DbgTrace(0, "-GetIdenTokenInterface- Parse error %d\n", XML_GetErrorCode(p));
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_PROTOCOL_ERROR);
}
// Free the parser
XML_ParserFree(p);
}
else
{
DbgTrace(0, "-CreateAuthToken- Parser creation error\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
// Return the Identity Token Interface to the caller if successful
if (CASA_SUCCESS(retStatus))
{
// Return the IdenTokenIf associated with the instance data after
// incrementing its reference count.
pIdenTokenIfInstance->refCount ++;
*ppIdenTokenIf = &pIdenTokenIfInstance->idenTokenIf;
// Bump up our interface instance count
PlatAcquireMutex(g_idenTokenIfMutex);
g_numIdenTokenIfObjs ++;
PlatReleaseMutex(g_idenTokenIfMutex);
}
else
{
FreeIdenTokenIfInstance(pIdenTokenIfInstance);
}
}
else
{
DbgTrace(0, "-GetIdenTokenInterface- Buffer allocation failure\n", 0);
retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
}
exit:
DbgTrace(2, "-GetIdenTokenInterface- End, retStatus = %0X\n", retStatus);
return retStatus;
}
//++=======================================================================
CasaStatus
IdenTokenIfInit(void)
//
// Arguments:
//
// Returns:
// Casa Status
//
// Description:
// Initializes the identity token interface complex.
//
// L2
//=======================================================================--
{
CasaStatus retStatus;
DbgTrace(1, "-IdenTokenIfInit- Start\n", 0);
// Allocate mutex
if ((g_idenTokenIfMutex = PlatAllocMutex()) != NULL)
retStatus = CASA_STATUS_SUCCESS;
else
retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_INSUFFICIENT_RESOURCES);
DbgTrace(1, "-IdenTokenIfInit- End, retStatus = %0X\n", retStatus);
return retStatus;
}
//++=======================================================================
void
IdenTokenIfUninit(void)
//
// Arguments:
//
// Returns:
// Casa Status
//
// Description:
// Uninitializes the configuration interface complex.
//
// L2
//=======================================================================--
{
DbgTrace(1, "-IdenTokenIfUninit- Start\n", 0);
// Free mutex if necessary
if (g_idenTokenIfMutex)
{
PlatDestroyMutex(g_idenTokenIfMutex);
g_idenTokenIfMutex = NULL;
}
DbgTrace(1, "-IdenTokenIfUninit- End\n", 0);
}
//++=======================================================================
//++=======================================================================
//++=======================================================================