/*********************************************************************** * * 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 * ***********************************************************************/ //===[ 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 size_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: * * * * identity id * identity data source name * identity data source url * target service name * target host name * * attribute value * attribute value * ... * * * */ // 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); } //++======================================================================= //++======================================================================= //++=======================================================================