/*********************************************************************** * * 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 ]================================================== // // Parse states // #define AWAITING_ROOT_ELEMENT_START 0x0 #define AWAITING_ROOT_ELEMENT_END 0x1 #define AWAITING_STATUS_ELEMENT_START 0x2 #define AWAITING_STATUS_ELEMENT_END 0x3 #define AWAITING_STATUS_DATA 0x4 #define AWAITING_DESCRIPTION_ELEMENT_START 0x5 #define AWAITING_DESCRIPTION_ELEMENT_END 0x6 #define AWAITING_DESCRIPTION_DATA 0x7 #define AWAITING_SESSION_TOKEN_ELEMENT_START 0x8 #define AWAITING_SESSION_TOKEN_ELEMENT_END 0x9 #define AWAITING_SESSION_TOKEN_DATA 0xA #define AWAITING_LIFETIME_DATA 0xB #define AWAITING_LIFETIME_ELEMENT_START 0xC #define AWAITING_LIFETIME_ELEMENT_END 0xD #define AWAITING_AUTH_TOKEN_ELEMENT_START 0xE #define AWAITING_AUTH_TOKEN_ELEMENT_END 0xF #define AWAITING_AUTH_TOKEN_DATA 0x10 #define AWAITING_AUTH_POLICY_ELEMENT_START 0x11 #define AWAITING_AUTH_POLICY_ELEMENT_END 0x12 #define AWAITING_AUTH_POLICY_DATA 0x13 #define AWAITING_AUTH_SOURCE_ELEMENT_START 0x14 #define AWAITING_AUTH_SOURCE_ELEMENT_END 0x15 #define AWAITING_AUTH_SOURCE_CHILD_START 0x16 #define AWAITING_REALM_DATA 0x17 #define AWAITING_REALM_ELEMENT_END 0x18 #define AWAITING_MECHANISM_DATA 0x19 #define AWAITING_MECHANISM_ELEMENT_END 0x1A #define AWAITING_MECHANISM_INFO_DATA 0x1B #define AWAITING_MECHANISM_INFO_ELEMENT_END 0x1C #define AWAITING_UNKNOWN_DATA 0x1D #define AWAITING_UNKNOWN_ELEMENT_END 0x1E #define DONE_PARSING 0x1F // // Authentication Policy Parse Structure // typedef struct _AuthPolicyParse { XML_Parser p; int state; AuthPolicy *pAuthPolicy; CasaStatus status; } AuthPolicyParse, *PAuthPolicyParse; // // Get Authentication Policy Response Parse Structure // typedef struct _GetAuthPolicyRespParse { XML_Parser p; int state; GetAuthPolicyResp *pGetAuthPolicyResp; CasaStatus status; } GetAuthPolicyRespParse, *PGetAuthPolicyRespParse; //===[ Function prototypes ]=============================================== //===[ Global variables ]================================================== //++======================================================================= static void XMLCALL AuthPolicyStartElementHandler( IN AuthPolicyParse *pAuthPolicyParse, IN const XML_Char *name, IN const XML_Char **atts) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { DbgTrace(2, "-AuthPolicyStartElementHandler- Start\n", 0); // Proceed based on the state switch (pAuthPolicyParse->state) { case AWAITING_ROOT_ELEMENT_START: // In this state, we are only expecting the Authentication // Policy Element. if (strcmp(name, AUTH_POLICY_ELEMENT_NAME) == 0) { // Good, advance to the next state. pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_ELEMENT_START; } else { DbgTrace(0, "-AuthPolicyStartElementHandler- Un-expected start element\n", 0); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } break; case AWAITING_AUTH_SOURCE_ELEMENT_START: case AWAITING_ROOT_ELEMENT_END: // In this state, we are only expecting the Authentication // Source Element. if (strcmp(name, AUTH_SOURCE_ELEMENT_NAME) == 0) { AuthContext *pAuthContext; // Create an authentication context structure pAuthContext = (AuthContext*) malloc(sizeof(AuthContext)); if (pAuthContext) { // Initialize the allocated AuthContext structure and associate it // with the AuthPolicy structure. memset(pAuthContext, 0, sizeof(*pAuthContext)); InsertTailList(&pAuthPolicyParse->pAuthPolicy->authContextListHead, &pAuthContext->listEntry); } else { DbgTrace(0, "-AuthPolicyStartElementHandler- Buffer allocation error\n", 0); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } // Good, advance to the next state. pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_CHILD_START; } else { DbgTrace(0, "-AuthPolicyStartElementHandler- Un-expected start element\n", 0); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } break; case AWAITING_AUTH_SOURCE_CHILD_START: // Proceed based on the name of the element if (strcmp(name, REALM_ELEMENT_NAME) == 0) { // Advance to the next state. pAuthPolicyParse->state = AWAITING_REALM_DATA; } else if (strcmp(name, MECHANISM_ELEMENT_NAME) == 0) { // Advance to the next state. pAuthPolicyParse->state = AWAITING_MECHANISM_DATA; } else if (strcmp(name, MECHANISM_INFO_ELEMENT_NAME) == 0) { // Advance to the next state. pAuthPolicyParse->state = AWAITING_MECHANISM_INFO_DATA; } else if (strcmp(name, AUTH_SOURCE_ELEMENT_NAME) == 0) { // We are starting a new auth source entry, create an authentication // context structure to hold its information. AuthContext *pAuthContext; // Create an authentication context structure pAuthContext = (AuthContext*) malloc(sizeof(AuthContext)); if (pAuthContext) { // Initialize the allocated AuthContext structure and associate it // with the AuthPolicy structure. memset(pAuthContext, 0, sizeof(*pAuthContext)); InsertTailList(&pAuthPolicyParse->pAuthPolicy->authContextListHead, &pAuthContext->listEntry); } else { DbgTrace(0, "-AuthPolicyStartElementHandler- Buffer allocation error\n", 0); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } } else { // Advance to the next state. pAuthPolicyParse->state = AWAITING_UNKNOWN_DATA; } break; default: DbgTrace(0, "-AuthPolicyStartElementHandler- Un-expected state = %d\n", pAuthPolicyParse->state); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); break; } DbgTrace(2, "-AuthPolicyStartElementHandler- End\n", 0); } //++======================================================================= static void XMLCALL AuthPolicyCharDataHandler( IN AuthPolicyParse *pAuthPolicyParse, IN const XML_Char *s, IN int len) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { AuthContext *pAuthContext; DbgTrace(2, "-AuthPolicyCharDataHandler- 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 (pAuthPolicyParse->state) { case AWAITING_REALM_DATA: // Get access to the AuthContext at the tail of the list pAuthContext = CONTAINING_RECORD(pAuthPolicyParse->pAuthPolicy->authContextListHead.Blink, AuthContext, listEntry); // Keep a copy of the realm data (null terminated) pAuthContext->pContext = (char*) malloc(len + 1); if (pAuthContext->pContext) { memset(pAuthContext->pContext, 0, len + 1); memcpy(pAuthContext->pContext, s, len); // Advanced to the next state pAuthPolicyParse->state = AWAITING_REALM_ELEMENT_END; } else { DbgTrace(0, "-AuthPolicyCharDataHandler- Buffer allocation failure\n", 0); pAuthPolicyParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } break; case AWAITING_MECHANISM_DATA: // Get access to the AuthContext at the tail of the list pAuthContext = CONTAINING_RECORD(pAuthPolicyParse->pAuthPolicy->authContextListHead.Blink, AuthContext, listEntry); // Keep a copy of the mechanism data (null terminated) pAuthContext->pMechanism = (char*) malloc(len + 1); if (pAuthContext->pMechanism) { memset(pAuthContext->pMechanism, 0, len + 1); memcpy(pAuthContext->pMechanism, s, len); // Advanced to the next state pAuthPolicyParse->state = AWAITING_MECHANISM_ELEMENT_END; } else { DbgTrace(0, "-AuthPolicyCharDataHandler- Buffer allocation failure\n", 0); pAuthPolicyParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } break; case AWAITING_MECHANISM_INFO_DATA: // Get access to the AuthContext at the tail of the list pAuthContext = CONTAINING_RECORD(pAuthPolicyParse->pAuthPolicy->authContextListHead.Blink, AuthContext, listEntry); // Keep a copy of the mechanism info data (null terminated) pAuthContext->pMechInfo = (char*) malloc(len + 1); if (pAuthContext->pMechInfo) { memset(pAuthContext->pMechInfo, 0, len + 1); memcpy(pAuthContext->pMechInfo, s, len); // Advanced to the next state pAuthPolicyParse->state = AWAITING_MECHANISM_INFO_ELEMENT_END; } else { DbgTrace(0, "-AuthPolicyCharDataHandler- Buffer allocation failure\n", 0); pAuthPolicyParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } break; case AWAITING_UNKNOWN_DATA: // Just advance the state pAuthPolicyParse->state = AWAITING_UNKNOWN_ELEMENT_END; break; default: DbgTrace(0, "-AuthPolicyCharDataHandler- Un-expected state = %d\n", pAuthPolicyParse->state); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); break; } exit: DbgTrace(2, "-AuthPolicyCharDataHandler- End\n", 0); } //++======================================================================= static void XMLCALL AuthPolicyEndElementHandler( IN AuthPolicyParse *pAuthPolicyParse, IN const XML_Char *name) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { AuthContext *pAuthContext; DbgTrace(2, "-AuthPolicyEndElementHandler- Start\n", 0); // Proceed based on the state switch (pAuthPolicyParse->state) { case AWAITING_ROOT_ELEMENT_END: // In this state, we are only expecting the Authentication // Policy Element. if (strcmp(name, AUTH_POLICY_ELEMENT_NAME) == 0) { // Done. pAuthPolicyParse->state = DONE_PARSING; } else { DbgTrace(0, "-AuthPolicyEndElementHandler- Un-expected end element\n", 0); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } break; case AWAITING_AUTH_SOURCE_CHILD_START: // In this state, we are only expecting the Authentication // Source Response Element. if (strcmp(name, AUTH_SOURCE_ELEMENT_NAME) == 0) { // Good, advance to the next state. pAuthPolicyParse->state = AWAITING_ROOT_ELEMENT_END; } else { DbgTrace(0, "-AuthPolicyEndHandler- Un-expected end element\n", 0); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } break; case AWAITING_REALM_ELEMENT_END: // In this state, we are only expecting the Realm Element. if (strcmp(name, REALM_ELEMENT_NAME) == 0) { // Good, advance to the next state. pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_CHILD_START; } else { DbgTrace(0, "-AuthPolicyEndElementHandler- Un-expected end element\n", 0); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } break; case AWAITING_MECHANISM_ELEMENT_END: // In this state, we are only expecting the Mechanism Element. if (strcmp(name, MECHANISM_ELEMENT_NAME) == 0) { // Good, advance to the next state. pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_CHILD_START; } else { DbgTrace(0, "-AuthPolicyEndElementHandler- Un-expected end element\n", 0); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } break; case AWAITING_MECHANISM_INFO_DATA: // Get access to the AuthContext at the tail of the list pAuthContext = CONTAINING_RECORD(pAuthPolicyParse->pAuthPolicy->authContextListHead.Blink, AuthContext, listEntry); // There was no mechanism info data. Set it to an empty string. pAuthContext->pMechInfo = (char*) malloc(1); if (pAuthContext->pMechInfo) { *pAuthContext->pMechInfo = '\0'; } else { DbgTrace(0, "-AuthPolicyEndElementHandler- Buffer allocation failure\n", 0); pAuthPolicyParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); break; } // Fall through case AWAITING_MECHANISM_INFO_ELEMENT_END: // In this state, we are only expecting the Mechanism Info Element. if (strcmp(name, MECHANISM_INFO_ELEMENT_NAME) == 0) { // Good, advance to the next state. pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_CHILD_START; } else { DbgTrace(0, "-AuthPolicyEndElementHandler- Un-expected end element\n", 0); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); } break; case AWAITING_UNKNOWN_ELEMENT_END: // Advance to the next state. pAuthPolicyParse->state = AWAITING_AUTH_SOURCE_CHILD_START; break; default: DbgTrace(0, "-AuthPolicyEndElementHandler- Un-expected state = %d\n", pAuthPolicyParse->state); XML_StopParser(pAuthPolicyParse->p, XML_FALSE); break; } DbgTrace(2, "-AuthPolicyEndElementHandler- End\n", 0); } //++======================================================================= CasaStatus CreateAuthPolicy( IN char *pEncodedData, IN int encodedDataLen, INOUT AuthPolicy **ppAuthPolicy) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { CasaStatus retStatus; AuthPolicy *pAuthPolicy = NULL; AuthPolicyParse authPolicyParse = {0}; char *pData = NULL; int dataLen = 0; DbgTrace(1, "-CreateAuthPolicy- Start\n", 0); // Initialize output parameter *ppAuthPolicy = NULL; // Decode the data retStatus = DecodeData(pEncodedData, encodedDataLen, &pData, &dataLen); if (CASA_SUCCESS(retStatus)) { // Allocate space for the AuthPolicy structure pAuthPolicy = (AuthPolicy*) malloc(sizeof(*pAuthPolicy)); if (pAuthPolicy) { XML_Parser p; // Initialize the list head within the structure InitializeListHead(&pAuthPolicy->authContextListHead); // Set the AuthPolicy object in the parse oject authPolicyParse.pAuthPolicy = pAuthPolicy; // Create parser p = XML_ParserCreate(NULL); if (p) { // Keep track of the parser in our parse object authPolicyParse.p = p; // Initialize the status within the parse object authPolicyParse.status = CASA_STATUS_SUCCESS; // Set the start and end element handlers XML_SetElementHandler(p, AuthPolicyStartElementHandler, AuthPolicyEndElementHandler); // Set the character data handler XML_SetCharacterDataHandler(p, AuthPolicyCharDataHandler); // Set our user data XML_SetUserData(p, &authPolicyParse); // Parse the document if (XML_Parse(p, pData, dataLen, 1) == XML_STATUS_OK) { // Verify that the parse operation completed successfully if (authPolicyParse.state == DONE_PARSING) { // The parse operation succeded retStatus = CASA_STATUS_SUCCESS; } else { DbgTrace(0, "-CreateAuthPolicy- Parse operation did not complete\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_PROTOCOL_ERROR); } } else { DbgTrace(0, "-CreateAuthPolicy- 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, "-CreateAuthPolicy- Parser creation error\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); } // Return the AuthPolicy object to the caller if necessary if (CASA_SUCCESS(retStatus)) { *ppAuthPolicy = pAuthPolicy; } } else { DbgTrace(0, "-CreateAuthPolicy- Buffer allocation error\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); } } else { DbgTrace(0, "-CreateAuthPolicy- Buffer allocation error\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); } // Release allocated resources if not successful if (!CASA_SUCCESS(retStatus) && pAuthPolicy) RelAuthPolicy(pAuthPolicy); DbgTrace(1, "-CreateAuthPolicy- End, retStatus = %08X\n", retStatus); return retStatus; } //++======================================================================= void RelAuthPolicy( IN AuthPolicy *pAuthPolicy) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { LIST_ENTRY *pListEntry; DbgTrace(1, "-RelAuthPolicy- Start\n", 0); // Free all of the associated AuthContexts pListEntry = pAuthPolicy->authContextListHead.Flink; while (pListEntry != &pAuthPolicy->authContextListHead) { AuthContext *pAuthContext; // Get pointer to AuthContext structure pAuthContext = CONTAINING_RECORD(pListEntry, AuthContext, listEntry); // Free associated buffers if (pAuthContext->pContext) free(pAuthContext->pContext); if (pAuthContext->pMechanism) free(pAuthContext->pMechanism); if (pAuthContext->pMechInfo) free(pAuthContext->pMechInfo); // Remove the entry from the list RemoveEntryList(&pAuthContext->listEntry); // Free the AuthContext free(pAuthContext); // Advance to the next entry pListEntry = pAuthPolicy->authContextListHead.Flink; } // Free the AuthPolicy free(pAuthPolicy); DbgTrace(1, "-RelAuthPolicy- End\n", 0); } //++======================================================================= char* BuildGetAuthPolicyMsg( IN char *pServiceName, IN char *pHostName) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { char *pMsg = NULL; int bufferSize; DbgTrace(1, "-BuildGetAuthPolicyMsg- Start\n", 0); /* * The format of the get authentication policy request message is as follows: * * * * service name<\service> * host name * * */ // Determine the buffer size necessary to hold the msg bufferSize = strlen(XML_DECLARATION) + 2 // crlf + 1 // < + strlen(GET_AUTH_POLICY_REQUEST_ELEMENT_NAME) + 3 // >crlf + 1 // < + strlen(SERVICE_ELEMENT_NAME) + 1 // > + strlen(pServiceName) + 2 // crlf + 2 // + strlen(pHostName) + 2 // crlf + 2 // null // Allocate the msg buffer pMsg = (char*) malloc(bufferSize); if (pMsg) { // Now build the message memset(pMsg, 0, bufferSize); strcat(pMsg, XML_DECLARATION); strcat(pMsg, "\r\n"); strcat(pMsg, "<"); strcat(pMsg, GET_AUTH_POLICY_REQUEST_ELEMENT_NAME); strcat(pMsg, ">\r\n"); strcat(pMsg, "<"); strcat(pMsg, SERVICE_ELEMENT_NAME); strcat(pMsg, ">"); strcat(pMsg, pServiceName); strcat(pMsg, "\r\n"); strcat(pMsg, "<"); strcat(pMsg, HOST_ELEMENT_NAME); strcat(pMsg, ">"); strcat(pMsg, pHostName); strcat(pMsg, "\r\n"); strcat(pMsg, ""); } else { DbgTrace(0, "-BuildGetAuthPolicyMsg- Buffer allocation error\n", 0); } DbgTrace(1, "-BuildGetAuthPolicyMsg- End, pMsg = %08X\n", pMsg); return pMsg; } //++======================================================================= static void XMLCALL GetAuthPolicyRespStartElementHandler( IN GetAuthPolicyRespParse *pGetAuthPolicyRespParse, IN const XML_Char *name, IN const XML_Char **atts) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { DbgTrace(2, "-GetAuthPolicyRespStartElementHandler- Start\n", 0); // Proceed based on the state switch (pGetAuthPolicyRespParse->state) { case AWAITING_ROOT_ELEMENT_START: // In this state, we are only expecting the Get Authentication // Policy Response Element. if (strcmp(name, GET_AUTH_POLICY_RESPONSE_ELEMENT_NAME) == 0) { // Good, advance to the next state. pGetAuthPolicyRespParse->state = AWAITING_STATUS_ELEMENT_START; } else { DbgTrace(0, "-GetAuthPolicyRespStartElementHandler- Un-expected start element\n", 0); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); } break; case AWAITING_STATUS_ELEMENT_START: // In this state, we are only expecting the Status Element. if (strcmp(name, STATUS_ELEMENT_NAME) == 0) { // Good, advance to the next state. pGetAuthPolicyRespParse->state = AWAITING_DESCRIPTION_ELEMENT_START; } else { DbgTrace(0, "-GetAuthPolicyRespStartElementHandler- Un-expected start element\n", 0); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); } break; case AWAITING_DESCRIPTION_ELEMENT_START: // In this state, we are only expecting the Description Element. if (strcmp(name, DESCRIPTION_ELEMENT_NAME) == 0) { // Good, advance to the next state. pGetAuthPolicyRespParse->state = AWAITING_DESCRIPTION_DATA; } else { DbgTrace(0, "-GetAuthPolicyRespStartElementHandler- Un-expected start element\n", 0); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); } break; case AWAITING_AUTH_POLICY_ELEMENT_START: // In this state, we are only expecting the Authentication Policy Element. if (strcmp(name, AUTH_POLICY_ELEMENT_NAME) == 0) { // Good, advance to the next state. pGetAuthPolicyRespParse->state = AWAITING_AUTH_POLICY_DATA; } else { DbgTrace(0, "-GetAuthPolicyRespStartElementHandler- Un-expected start element\n", 0); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); } break; default: DbgTrace(0, "-GetAuthPolicyRespStartElementHandler- Un-expected state = %d\n", pGetAuthPolicyRespParse->state); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); break; } DbgTrace(2, "-GetAuthPolicyRespStartElementHandler- End\n", 0); } //++======================================================================= static void XMLCALL GetAuthPolicyRespCharDataHandler( IN GetAuthPolicyRespParse *pGetAuthPolicyRespParse, IN const XML_Char *s, IN int len) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { DbgTrace(2, "-GetAuthPolicyRespCharDataHandler- 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 (pGetAuthPolicyRespParse->state) { case AWAITING_DESCRIPTION_DATA: // Ignore the status description data for now. // Advanced to the next state pGetAuthPolicyRespParse->state = AWAITING_DESCRIPTION_ELEMENT_END; break; case AWAITING_STATUS_DATA: // Set the appropriate status in the AuthenticationResp based on the // returned status. if (strncmp(HTTP_OK_STATUS_CODE, s, len) == 0) { pGetAuthPolicyRespParse->status = CASA_STATUS_SUCCESS; } else if (strncmp(HTTP_UNAUTHORIZED_STATUS_CODE, s, len) == 0) { pGetAuthPolicyRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_AUTHENTICATION_FAILURE); } else if (strncmp(HTTP_SERVER_ERROR_STATUS_CODE, s, len) == 0) { pGetAuthPolicyRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_SERVER_ERROR); } else { DbgTrace(0, "-GetAuthPolicyRespCharDataHandler- Un-expected status\n", 0); pGetAuthPolicyRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_UNSUCCESSFUL); } // Advanced to the next state pGetAuthPolicyRespParse->state = AWAITING_STATUS_ELEMENT_END; break; case AWAITING_AUTH_POLICY_DATA: case AWAITING_AUTH_POLICY_ELEMENT_END: // Check if we have already processed policy data if (pGetAuthPolicyRespParse->pGetAuthPolicyResp->policyLen == 0) { // Keep a copy of the policy (null terminated) pGetAuthPolicyRespParse->pGetAuthPolicyResp->pPolicy = (char*) malloc(len + 1); if (pGetAuthPolicyRespParse->pGetAuthPolicyResp->pPolicy) { memset(pGetAuthPolicyRespParse->pGetAuthPolicyResp->pPolicy, 0, len + 1); memcpy(pGetAuthPolicyRespParse->pGetAuthPolicyResp->pPolicy, s, len); pGetAuthPolicyRespParse->pGetAuthPolicyResp->policyLen = len; // Advanced to the next state pGetAuthPolicyRespParse->state = AWAITING_AUTH_POLICY_ELEMENT_END; } else { DbgTrace(0, "-GetAuthPolicyRespCharDataHandler- Buffer allocation failure\n", 0); pGetAuthPolicyRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); } } else { char *pNewBuf; // We have already received token data, append this data to it. pNewBuf = (char*) malloc(pGetAuthPolicyRespParse->pGetAuthPolicyResp->policyLen + len + 1); if (pNewBuf) { memset(pNewBuf, 0, pGetAuthPolicyRespParse->pGetAuthPolicyResp->policyLen + len + 1); memcpy(pNewBuf, pGetAuthPolicyRespParse->pGetAuthPolicyResp->pPolicy, pGetAuthPolicyRespParse->pGetAuthPolicyResp->policyLen); memcpy(pNewBuf + pGetAuthPolicyRespParse->pGetAuthPolicyResp->policyLen, s, len); pGetAuthPolicyRespParse->pGetAuthPolicyResp->policyLen += len; // Swap the buffers free(pGetAuthPolicyRespParse->pGetAuthPolicyResp->pPolicy); pGetAuthPolicyRespParse->pGetAuthPolicyResp->pPolicy = pNewBuf; } else { DbgTrace(0, "-GetAuthPolicyRespCharDataHandler- Buffer allocation failure\n", 0); pGetAuthPolicyRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); } } break; default: DbgTrace(0, "-GetAuthPolicyRespCharDataHandler- Un-expected state = %d\n", pGetAuthPolicyRespParse->state); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); break; } exit: DbgTrace(2, "-GetAuthPolicyRespCharDataHandler- End\n", 0); } //++======================================================================= static void XMLCALL GetAuthPolicyRespEndElementHandler( IN GetAuthPolicyRespParse *pGetAuthPolicyRespParse, IN const XML_Char *name) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { DbgTrace(2, "-GetAuthPolicyRespEndElementHandler- Start\n", 0); // Proceed based on the state switch (pGetAuthPolicyRespParse->state) { case AWAITING_ROOT_ELEMENT_END: // In this state, we are only expecting the Get Authentication // Policy Response Element. if (strcmp(name, GET_AUTH_POLICY_RESPONSE_ELEMENT_NAME) == 0) { // Done. pGetAuthPolicyRespParse->state = DONE_PARSING; } else { DbgTrace(0, "-GetAuthPolicyRespEndHandler- Un-expected end element\n", 0); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); } break; case AWAITING_DESCRIPTION_ELEMENT_END: // In this state, we are only expecting the Description Element. if (strcmp(name, DESCRIPTION_ELEMENT_NAME) == 0) { // Good, advance to the next state. pGetAuthPolicyRespParse->state = AWAITING_STATUS_DATA; } else { DbgTrace(0, "-GetAuthPolicyRespEndElementHandler- Un-expected end element\n", 0); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); } break; case AWAITING_STATUS_ELEMENT_END: // In this state, we are only expecting the Status Element. if (strcmp(name, STATUS_ELEMENT_NAME) == 0) { // Good, advance to the next state based on the status code. if (CASA_SUCCESS(pGetAuthPolicyRespParse->status)) { // The request completed successfully pGetAuthPolicyRespParse->state = AWAITING_AUTH_POLICY_ELEMENT_START; } else { pGetAuthPolicyRespParse->state = AWAITING_ROOT_ELEMENT_END; } } else { DbgTrace(0, "-GetAuthPolicyRespEndElementHandler- Un-expected start element\n", 0); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); } break; case AWAITING_AUTH_POLICY_ELEMENT_END: // In this state, we are only expecting the Authentication Policy Element. if (strcmp(name, AUTH_POLICY_ELEMENT_NAME) == 0) { // Good, advance to the next state. pGetAuthPolicyRespParse->state = AWAITING_ROOT_ELEMENT_END; } else { DbgTrace(0, "-GetAuthPolicyRespEndElementHandler- Un-expected start element\n", 0); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); } break; default: DbgTrace(0, "-GetAuthPolicyRespEndElementHandler- Un-expected state = %d\n", pGetAuthPolicyRespParse->state); XML_StopParser(pGetAuthPolicyRespParse->p, XML_FALSE); break; } DbgTrace(2, "-GetAuthPolicyRespEndElementHandler- End\n", 0); } //++======================================================================= CasaStatus CreateGetAuthPolicyResp( IN char *pRespMsg, IN int respLen, INOUT GetAuthPolicyResp **ppGetAuthPolicyResp) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { CasaStatus retStatus = CASA_STATUS_SUCCESS; GetAuthPolicyRespParse getAuthPolicyRespParse = {0}; GetAuthPolicyResp *pGetAuthPolicyResp; DbgTrace(1, "-CreateGetAuthPolicyResp- Start\n", 0); /* * When a get authentication policy request is processed successfully, the * server replies to the client with a message with the following format: * * * * ok200 * authentication policy data * * * When a get authentication policy request fails to be successfully processed, * the server responds with an error and a error description string. The message * format of an unsuccessful reply is as follows: * * * * status descriptionstatus code * * * Plase note that the protocol utilizes the status codes defined * in the HTTP 1.1 Specification. * */ // Allocate GetAuthPolicyResp object pGetAuthPolicyResp = malloc(sizeof(*pGetAuthPolicyResp)); if (pGetAuthPolicyResp) { XML_Parser p; // Initialize the GetAuthPolicyResp object and set it in the // parse oject. memset(pGetAuthPolicyResp, 0, sizeof(*pGetAuthPolicyResp)); getAuthPolicyRespParse.pGetAuthPolicyResp = pGetAuthPolicyResp; // Create parser p = XML_ParserCreate(NULL); if (p) { // Keep track of the parser in our parse object getAuthPolicyRespParse.p = p; // Initialize the status within the parse object getAuthPolicyRespParse.status = CASA_STATUS_SUCCESS; // Set the start and end element handlers XML_SetElementHandler(p, GetAuthPolicyRespStartElementHandler, GetAuthPolicyRespEndElementHandler); // Set the character data handler XML_SetCharacterDataHandler(p, GetAuthPolicyRespCharDataHandler); // Set our user data XML_SetUserData(p, &getAuthPolicyRespParse); // Parse the document if (XML_Parse(p, pRespMsg, respLen, 1) == XML_STATUS_OK) { // Verify that the parse operation completed successfully if (getAuthPolicyRespParse.state == DONE_PARSING) { // The parse operation succeded, obtain the status returned // by the server. retStatus = getAuthPolicyRespParse.status; } else { DbgTrace(0, "-CreateGetAuthPolicyResp- Parse operation did not complete\n", 0); // Check if a status has been recorded if (getAuthPolicyRespParse.status != CASA_STATUS_SUCCESS) { retStatus = getAuthPolicyRespParse.status; } else { retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_PROTOCOL_ERROR); } } } else { DbgTrace(0, "-CreateGetAuthPolicyResp- 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, "-CreateGetAuthPolicyResp- Parser creation error\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); } // Return the AuthenticationResp object to the caller if necessary if (CASA_SUCCESS(retStatus)) { *ppGetAuthPolicyResp = pGetAuthPolicyResp; } else { free(pGetAuthPolicyResp); } } else { DbgTrace(0, "-CreateGetAuthPolicyResp- Memory allocation error\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INSUFFICIENT_RESOURCES); } DbgTrace(1, "-CreateGetAuthPolicyResp- End, retStatus = %08X\n", retStatus); return retStatus; } //++======================================================================= void RelGetAuthPolicyResp( IN GetAuthPolicyResp *pGetAuthPolicyResp) // // Arguments: // // Returns: // // Abstract: // // Notes: // // L0 //=======================================================================-- { DbgTrace(1, "-RelGetAuthPolicyResp- Start\n", 0); // Free the buffer holding the authentication policy if (pGetAuthPolicyResp->pPolicy) free(pGetAuthPolicyResp->pPolicy); // Free the GetAuthPolicyResp free(pGetAuthPolicyResp); DbgTrace(1, "-RelGetAuthPolicyResp- End\n", 0); }