diff --git a/auth_token/client/authmech.c b/auth_token/client/authmech.c new file mode 100644 index 00000000..8f579bd6 --- /dev/null +++ b/auth_token/client/authmech.c @@ -0,0 +1,333 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// AuthMechMod definition +// +typedef struct _AuthMechMod +{ + LIST_ENTRY listEntry; + char *pAuthTypeName; + int authTypeNameLen; + LIB_HANDLE libHandle; + AuthTokenIf *pAuthTokenIf; + +} AuthMechMod, *PAuthMechMod; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// AuthMechModule List and syncronizing mutex +static +LIST_ENTRY g_authMechModuleListHead = {&g_authMechModuleListHead, + &g_authMechModuleListHead}; + + +//++======================================================================= +static +CasaStatus +GetAuthTokenIf( + IN const char *pAuthTypeName, + INOUT AuthTokenIf **ppAuthTokenIf) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// Environment: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + ConfigIf *pModuleConfigIf; + + + DbgTrace(2, "-GetAuthTokenIf- Start\n", 0); + + // Get the configuration for the module + retStatus = GetConfigInterface(mechConfigFolder, + pAuthTypeName, + &pModuleConfigIf); + if (CASA_SUCCESS(retStatus) + && CasaStatusCode(retStatus) != CASA_STATUS_OBJECT_NOT_FOUND) + { + LIST_ENTRY *pListEntry; + AuthMechMod *pAuthMechMod = NULL; + int32_t authTypeNameLen = (int32_t) strlen(pAuthTypeName); + + // Look if we already have the module in our list + pListEntry = g_authMechModuleListHead.Flink; + while (pListEntry != &g_authMechModuleListHead) + { + // Get pointer to the current entry + pAuthMechMod = CONTAINING_RECORD(pListEntry, AuthMechMod, listEntry); + + // Check if this is the module that we need + if (pAuthMechMod->authTypeNameLen == authTypeNameLen + && memcmp(pAuthTypeName, pAuthMechMod->pAuthTypeName, authTypeNameLen) == 0) + { + // This is the module that we need, stop looking. + break; + } + else + { + // This is not the module that we are looking for + pAuthMechMod = NULL; + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Proceed based on whether or not a module was found + if (pAuthMechMod) + { + // Module found in our list, provide the caller with its AuthTokenIf + // instance after we have incremented its reference count. + pAuthMechMod->pAuthTokenIf->addReference(pAuthMechMod->pAuthTokenIf); + *ppAuthTokenIf = pAuthMechMod->pAuthTokenIf; + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + // Needed module not found in our list, create an entry. + pAuthMechMod = (AuthMechMod*) malloc(sizeof(*pAuthMechMod)); + if (pAuthMechMod) + { + // Allocate buffer to contain the authentication type name within the module entry + pAuthMechMod->pAuthTypeName = (char*) malloc(authTypeNameLen + 1); + if (pAuthMechMod->pAuthTypeName) + { + char *pLibraryName; + + // Initialize the library handle field + pAuthMechMod->libHandle = NULL; + + // Save the auth type name within the entry + strcpy(pAuthMechMod->pAuthTypeName, pAuthTypeName); + pAuthMechMod->authTypeNameLen = authTypeNameLen; + + // Obtain the name of the library that we must load + pLibraryName = pModuleConfigIf->getEntryValue(pModuleConfigIf, "LibraryName"); + if (pLibraryName) + { + // Load the library + pAuthMechMod->libHandle = OpenLibrary(pLibraryName); + if (pAuthMechMod->libHandle) + { + PFN_GetAuthTokenIfRtn pGetAuthTokenIfRtn; + + // Library has been loaded, now get a pointer to its GetAuthTokenInterface routine + pGetAuthTokenIfRtn = (PFN_GetAuthTokenIfRtn) GetFunctionPtr(pAuthMechMod->libHandle, + GET_AUTH_TOKEN_INTERFACE_RTN_SYMBOL); + if (pGetAuthTokenIfRtn) + { + // Now, obtain the modules AuthTokenIf. + retStatus = (pGetAuthTokenIfRtn)(pModuleConfigIf, &pAuthMechMod->pAuthTokenIf); + } + else + { + DbgTrace(0, "-GetAuthTokenIf- GetFunctionPtr\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_LIBRARY_LOAD_FAILURE); + } + } + else + { + DbgTrace(0, "-GetAuthTokenIf- OpenLibrary error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Free the buffer holding the library name + free(pLibraryName); + } + else + { + DbgTrace(0, "-GetAuthTokenIf- Library name not configured\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_CONFIGURATION_ERROR); + } + + // Check if we were successful at obtaining the AuthTokenIf instance for the + // module. + if (CASA_SUCCESS(retStatus)) + { + // Insert the entry in the list, provide the caller with its AuthTokenIf + // instance after we have incremented its reference count. + InsertTailList(&g_authMechModuleListHead, &pAuthMechMod->listEntry); + pAuthMechMod->pAuthTokenIf->addReference(pAuthMechMod->pAuthTokenIf); + *ppAuthTokenIf = pAuthMechMod->pAuthTokenIf; + } + else + { + // Failed, free resources. + free(pAuthMechMod->pAuthTypeName); + if (pAuthMechMod->libHandle) + CloseLibrary(pAuthMechMod->libHandle); + free(pAuthMechMod); + } + } + else + { + DbgTrace(0, "GetAuthTokenIf-GetAuthTokenIf- Unable to allocate buffer\n", 0); + + // Free buffer allocated for entry + free(pAuthMechMod); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + DbgTrace(0, "-GetAuthTokenIf- Unable to allocate buffer\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + + // Release config interface instance + pModuleConfigIf->releaseReference(pModuleConfigIf); + } + else + { + DbgTrace(0, "-GetAuthTokenIf- Unable to obtain config interface\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_CONFIGURATION_ERROR); + } + + DbgTrace(2, "-GetAuthTokenIf- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +GetAuthMechToken( + IN AuthContext *pAuthContext, + INOUT char **ppAuthToken) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + AuthTokenIf *pAuthTokenIf; + + DbgTrace(1, "-GetAuthMechToken- Start\n", 0); + + // Initialize output parameter + *ppAuthToken = NULL; + + // Obtain the appropriate token interface for the authentication type + retStatus = GetAuthTokenIf(pAuthContext->pMechanism, + &pAuthTokenIf); + if (CASA_SUCCESS(retStatus)) + { + char *pAuthToken = NULL; + int authTokenBufLen = 0; + + // We found a provider for the service, query it for the buffer size + // needed to obtain the authentication token. + retStatus = pAuthTokenIf->getAuthToken(pAuthTokenIf, + pAuthContext->pContext, + pAuthContext->pMechInfo, + pAuthToken, + &authTokenBufLen); + if (CasaStatusCode(retStatus) == CASA_STATUS_BUFFER_OVERFLOW) + { + // Allocate buffer to hold the authentication token + pAuthToken = (char*) malloc(authTokenBufLen); + if (pAuthToken) + { + // Request the token from the provider + retStatus = pAuthTokenIf->getAuthToken(pAuthTokenIf, + pAuthContext->pContext, + pAuthContext->pMechInfo, + pAuthToken, + &authTokenBufLen); + if (CASA_SUCCESS(retStatus)) + { + // Return the buffer containing the token to the caller + *ppAuthToken = pAuthToken; + } + else + { + // Free the allocated buffer + free(pAuthToken); + } + } + else + { + DbgTrace(0, "-GetAuthMechToken- Buffer allocation failure\n", 0); + } + } + + // Release token interface + pAuthTokenIf->releaseReference(pAuthTokenIf); + } + else + { + // No authentication token interface available for authentication type + DbgTrace(0, "-GetAuthMechToken- Failed to obtain auth mech token interface\n", 0); + } + + DbgTrace(1, "-GetAuthMechToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + diff --git a/auth_token/client/authmsg.c b/auth_token/client/authmsg.c new file mode 100644 index 00000000..bc4a27d4 --- /dev/null +++ b/auth_token/client/authmsg.c @@ -0,0 +1,725 @@ +/*********************************************************************** + * + * 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_REALM_DATA 0x12 +#define AWAITING_REALM_ELEMENT_END 0x13 +#define DONE_PARSING 0x14 + +// +// Authentication Response Parse Structure +// +typedef struct _AuthRespParse +{ + XML_Parser p; + int state; + int tokenDataProcessed; + AuthenticateResp *pAuthenticateResp; + CasaStatus status; + +} AuthRespParse, *PAuthRespParse; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//++======================================================================= +char* +BuildAuthenticateMsg( + IN AuthContext *pAuthContext, + IN char *pAuthMechToken) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + char *pMsg = NULL; + int bufferSize; + + DbgTrace(1, "-BuildAuthenticateMsg- Start\n", 0); + + /* + * The format of the authentication request message is as follows: + * + * + * + * realm value + * authentication mechanism token data + * + * + */ + + // Determine the buffer size necessary to hold the msg + bufferSize = strlen(XML_DECLARATION) + + 2 // crlf + + 1 // < + + strlen(AUTH_REQUEST_ELEMENT_NAME) + + 3 // >crlf + + 1 // < + + strlen(REALM_ELEMENT_NAME) + + 1 // > + + strlen(pAuthContext->pContext) + + 2 // crlf + + 1 // < + + strlen(AUTH_MECH_TOKEN_ELEMENT_NAME) + + 1 // > + + strlen(pAuthMechToken) + + 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, AUTH_REQUEST_ELEMENT_NAME); + strcat(pMsg, ">\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, REALM_ELEMENT_NAME); + strcat(pMsg, ">"); + strcat(pMsg, pAuthContext->pContext); + strcat(pMsg, "\r\n"); + strcat(pMsg, "<"); + strcat(pMsg, AUTH_MECH_TOKEN_ELEMENT_NAME); + strcat(pMsg, ">"); + strcat(pMsg, pAuthMechToken); + strcat(pMsg, "\r\n"); + strcat(pMsg, ""); + } + else + { + DbgTrace(0, "-BuildAuthenticateMsg- Buffer allocation error\n", 0); + } + + DbgTrace(1, "-BuildAuthenticateMsg- End, pMsg = %08X\n", pMsg); + + return pMsg; +} + + +//++======================================================================= +static +void XMLCALL +AuthRespStartElementHandler( + IN AuthRespParse *pAuthRespParse, + IN const XML_Char *name, + IN const XML_Char **atts) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + DbgTrace(2, "-AuthRespStartElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pAuthRespParse->state) + { + case AWAITING_ROOT_ELEMENT_START: + + // In this state, we are only expecting the Authentication + // Response Element. + if (strcmp(name, AUTH_RESPONSE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_STATUS_ELEMENT_START; + } + else + { + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->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. + pAuthRespParse->state = AWAITING_DESCRIPTION_ELEMENT_START; + } + else + { + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->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. + pAuthRespParse->state = AWAITING_DESCRIPTION_DATA; + } + else + { + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_SESSION_TOKEN_ELEMENT_START: + + // In this state, we are only expecting the Session Token Element. + if (strcmp(name, SESSION_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_LIFETIME_ELEMENT_START; + } + else + { + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_LIFETIME_ELEMENT_START: + + // In this state, we are only expecting the Lifetime Element. + if (strcmp(name, LIFETIME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_LIFETIME_DATA; + } + else + { + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-AuthRespStartElementHandler- Un-expected state = %d\n", pAuthRespParse->state); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-AuthRespStartElementHandler- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +AuthRespCharDataHandler( + IN AuthRespParse *pAuthRespParse, + IN const XML_Char *s, + IN int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + DbgTrace(2, "-AuthRespCharDataHandler- 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 (pAuthRespParse->state) + { + case AWAITING_DESCRIPTION_DATA: + + // Ignore the status description data for now. + + // Advanced to the next state + pAuthRespParse->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) + { + pAuthRespParse->status = CASA_STATUS_SUCCESS; + } + else if (strncmp(HTTP_UNAUTHORIZED_STATUS_CODE, s, len) == 0) + { + pAuthRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_AUTHENTICATION_FAILURE); + } + else if (strncmp(HTTP_SERVER_ERROR_STATUS_CODE, s, len) == 0) + { + pAuthRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_SERVER_ERROR); + } + else + { + DbgTrace(0, "-AuthRespCharDataHandler- Un-expected status\n", 0); + pAuthRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Advanced to the next state + pAuthRespParse->state = AWAITING_STATUS_ELEMENT_END; + break; + + case AWAITING_LIFETIME_DATA: + + // Convert the lifetime string to a numeric value + pAuthRespParse->pAuthenticateResp->tokenLifetime = dtoul(s, len); + + // Advanced to the next state + pAuthRespParse->state = AWAITING_LIFETIME_ELEMENT_END; + break; + + case AWAITING_SESSION_TOKEN_DATA: + case AWAITING_SESSION_TOKEN_ELEMENT_END: + + // Check if we have already processed token data + if (pAuthRespParse->tokenDataProcessed == 0) + { + // Keep a copy of the session token (null terminated) + pAuthRespParse->pAuthenticateResp->pToken = (char*) malloc(len + 1); + if (pAuthRespParse->pAuthenticateResp->pToken) + { + memset(pAuthRespParse->pAuthenticateResp->pToken, 0, len + 1); + memcpy(pAuthRespParse->pAuthenticateResp->pToken, s, len); + pAuthRespParse->tokenDataProcessed = len; + + // Advanced to the next state + pAuthRespParse->state = AWAITING_SESSION_TOKEN_ELEMENT_END; + } + else + { + DbgTrace(0, "-AuthRespCharDataHandler- Buffer allocation failure\n", 0); + pAuthRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + } + else + { + char *pNewBuf; + + // We have already received token data, append this data to it. + pNewBuf = (char*) malloc(pAuthRespParse->tokenDataProcessed + len + 1); + if (pNewBuf) + { + memset(pNewBuf, + 0, + pAuthRespParse->tokenDataProcessed + len + 1); + memcpy(pNewBuf, + pAuthRespParse->pAuthenticateResp->pToken, + pAuthRespParse->tokenDataProcessed); + memcpy(pNewBuf + pAuthRespParse->tokenDataProcessed, s, len); + pAuthRespParse->tokenDataProcessed += len; + + // Swap the buffers + free(pAuthRespParse->pAuthenticateResp->pToken); + pAuthRespParse->pAuthenticateResp->pToken = pNewBuf; + } + else + { + DbgTrace(0, "-AuthRespCharDataHandler- Buffer allocation failure\n", 0); + pAuthRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + } + break; + + default: + DbgTrace(0, "-AuthRespCharDataHandler- Un-expected state = %d\n", pAuthRespParse->state); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + break; + } + +exit: + + DbgTrace(2, "-AuthRespCharDataHandler- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +AuthRespEndElementHandler( + IN AuthRespParse *pAuthRespParse, + IN const XML_Char *name) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + DbgTrace(2, "-AuthRespEndElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pAuthRespParse->state) + { + case AWAITING_ROOT_ELEMENT_END: + + // In this state, we are only expecting the Authentication + // Response Element. + if (strcmp(name, AUTH_RESPONSE_ELEMENT_NAME) == 0) + { + // Done. + pAuthRespParse->state = DONE_PARSING; + } + else + { + DbgTrace(0, "-AuthRespEndHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthRespParse->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. + pAuthRespParse->state = AWAITING_STATUS_DATA; + } + else + { + DbgTrace(0, "-AuthRespEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pAuthRespParse->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(pAuthRespParse->status)) + { + // The request completed successfully + pAuthRespParse->state = AWAITING_SESSION_TOKEN_ELEMENT_START; + } + else + { + pAuthRespParse->state = AWAITING_ROOT_ELEMENT_END; + } + } + else + { + DbgTrace(0, "-AuthRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_LIFETIME_ELEMENT_END: + + // In this state, we are only expecting the Lifetime Element. + if (strcmp(name, LIFETIME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_SESSION_TOKEN_DATA; + } + else + { + DbgTrace(0, "-AuthRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + case AWAITING_SESSION_TOKEN_ELEMENT_END: + + // In this state, we are only expecting the Session Token Element. + if (strcmp(name, SESSION_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pAuthRespParse->state = AWAITING_ROOT_ELEMENT_END; + } + else + { + DbgTrace(0, "-AuthRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-AuthRespEndElementHandler- Un-expected state = %d\n", pAuthRespParse->state); + XML_StopParser(pAuthRespParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-AuthRespEndElementHandler- End\n", 0); +} + + +//++======================================================================= +CasaStatus +CreateAuthenticateResp( + IN char *pRespMsg, + IN int respLen, + INOUT AuthenticateResp **ppAuthenticateResp) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + AuthRespParse authRespParse = {0}; + AuthenticateResp *pAuthenticateResp; + + DbgTrace(1, "-CreateAuthenticateResp- Start\n", 0); + + /* + * When an authentication request is processed successfully, the server replies to + * the client with a message with the following format: + * + * + * + * ok200 + * lifetime valuesession token data + * + * + * When an authentication 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 AuthenticateResp object + pAuthenticateResp = malloc(sizeof(*pAuthenticateResp)); + if (pAuthenticateResp) + { + XML_Parser p; + + // Initialize the AuthenticateResp object and set it in the + // authentication response parse oject. + memset(pAuthenticateResp, 0, sizeof(*pAuthenticateResp)); + authRespParse.pAuthenticateResp = pAuthenticateResp; + + // Create parser + p = XML_ParserCreate(NULL); + if (p) + { + // Keep track of the parser in our parse object + authRespParse.p = p; + + // Initialize the status within the parse object + authRespParse.status = CASA_STATUS_SUCCESS; + + // Set the start and end element handlers + XML_SetElementHandler(p, + AuthRespStartElementHandler, + AuthRespEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, AuthRespCharDataHandler); + + + // Set our user data + XML_SetUserData(p, &authRespParse); + + // Parse the document + if (XML_Parse(p, pRespMsg, respLen, 1) == XML_STATUS_OK) + { + // Verify that the parse operation completed successfully + if (authRespParse.state == DONE_PARSING) + { + // The parse operation succeded, obtain the status returned + // by the server. + retStatus = authRespParse.status; + } + else + { + DbgTrace(0, "-CreateAuthenticateResp- Parse operation did not complete\n", 0); + + // Check if a status has been recorded + if (authRespParse.status != CASA_STATUS_SUCCESS) + { + retStatus = authRespParse.status; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + } + } + else + { + DbgTrace(0, "-CreateAuthenticateResp- 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, "-CreateAuthenticateResp- 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)) + { + *ppAuthenticateResp = pAuthenticateResp; + } + else + { + free(pAuthenticateResp); + } + } + else + { + DbgTrace(0, "-CreateAuthenticateResp- Memory allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(1, "-CreateAuthenticateResp- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +RelAuthenticateResp( + IN AuthenticateResp *pAuthenticateResp) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + DbgTrace(1, "-RelAuthenticateResp- Start\n", 0); + + // Free the resources associated with the object + if (pAuthenticateResp->pToken) + free(pAuthenticateResp->pToken); + + free(pAuthenticateResp); + + DbgTrace(1, "-RelAuthenticateResp- End\n", 0); +} + diff --git a/auth_token/client/client.vcproj b/auth_token/client/client.vcproj new file mode 100644 index 00000000..048b2283 --- /dev/null +++ b/auth_token/client/client.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/auth_token/client/config.c b/auth_token/client/config.c new file mode 100644 index 00000000..fa6c601b --- /dev/null +++ b/auth_token/client/config.c @@ -0,0 +1,685 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// Config Key object +// +typedef struct _ConfigKey +{ + LIST_ENTRY listEntry; + char *pKeyName; + int keyNameLen; + char *pValue; + int valueLen; + +} ConfigKey, *pConfigKey; + +// +// Config Interface instance data +// +typedef struct _ConfigIfInstance +{ + LIST_ENTRY listEntry; + int refCount; + char *pConfigFolder; + int configFolderLen; + char *pConfigName; + int configNameLen; + LIST_ENTRY configKeyListHead; + ConfigIf configIf; + +} ConfigIfInstance, *PConfigIfInstance; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// ConfigIf variables +static +LIST_ENTRY g_configIfListHead = {&g_configIfListHead, &g_configIfListHead}; + +static +int g_numConfigIfObjs = 0; + + +//++======================================================================= +static void +RemoveWhiteSpaceFromTheEnd( + IN const char *pInString) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + char *pLineEnd = (char*) pInString + strlen(pInString) - 1; + + + DbgTrace(3, "-RemoveWhiteSpaceFromTheEnd- Start\n", 0); + + while (pLineEnd != pInString) + { + if (*pLineEnd == '\n' + || *pLineEnd == ' ' + || *pLineEnd == '\t') + { + // Strike this character + *pLineEnd = '\0'; + pLineEnd --; + } + else + { + // Found a non-white character + break; + } + } + + DbgTrace(3, "-RemoveWhiteSpaceFromTheEnd- End\n", 0); +} + + +//++======================================================================= +static char* +SkipWhiteSpace( + IN const char *pInString) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + char *pOutString = (char*) pInString; + + DbgTrace(3, "-SkipWhiteSpace- Start\n", 0); + + while (*pOutString != '\0') + { + if (*pOutString == '\n' + || *pOutString == ' ' + || *pOutString == '\t') + { + // Skip this character + pOutString ++; + } + else + { + // Found a non-white character + break; + } + } + + DbgTrace(3, "-SkipWhiteSpace- End\n", 0); + + return pOutString; +} + + +//++======================================================================= +static char* +SkipNonWhiteSpace( + IN const char *pInString) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + char *pOutString = (char*) pInString; + + DbgTrace(3, "-SkipNonWhiteSpace- Start\n", 0); + + while (*pOutString != '\0') + { + if (*pOutString == '\n' + || *pOutString == ' ' + || *pOutString == '\t') + { + // Found a white character + break; + } + else + { + // Skip this character + pOutString ++; + } + } + + DbgTrace(3, "-SkipNonWhiteSpace- End\n", 0); + + return pOutString; +} + + +//++======================================================================= +static void +LowerCaseString( + IN char *pDestString, + IN const char *pSrcString) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L2 +//=======================================================================-- +{ + int i; + + DbgTrace(3, "-LowerCaseString- Start\n", 0); + + // Copy the string as lower case + for (i = 0; pSrcString[i] != '\0'; i++) + { + if (isalpha(pSrcString[i])) + pDestString[i] = tolower(pSrcString[i]); + else + pDestString[i] = pSrcString[i]; + } + + // Null terminate the destination string + pDestString[i] = '\0'; + + DbgTrace(3, "-LowerCaseString- End\n", 0); +} + + +//++======================================================================= +int SSCS_CALL +ConfigIf_AddReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +// +// L2 +//=======================================================================-- +{ + int refCount; + ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf); + + DbgTrace(2, "-ConfigIf_AddReference- Start\n", 0); + + // Increment the reference count on the object + pConfigIfInstance->refCount ++; + refCount = pConfigIfInstance->refCount; + + DbgTrace(2, "-ConfigIf_AddReference- End, refCount = %08X\n", refCount); + + return refCount; +} + + +//++======================================================================= +void SSCS_CALL +ConfigIf_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; + ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf); + + DbgTrace(2, "-ConfigIf_ReleaseReference- Start\n", 0); + + // Decrement the reference count on the object and determine if it needs to + // be released. + pConfigIfInstance->refCount --; + if (pConfigIfInstance->refCount == 0) + { + // The object needs to be released, forget about it. + freeObj = true; + g_numConfigIfObjs --; + RemoveEntryList(&pConfigIfInstance->listEntry); + } + + // Free object if necessary + if (freeObj) + { + // Free all of the config key objects associated with this configuration + // interface instance. + while (!IsListEmpty(&pConfigIfInstance->configKeyListHead)) + { + LIST_ENTRY *pListEntry; + ConfigKey *pConfigKey; + + // Get reference to entry at the head of the list + pListEntry = pConfigIfInstance->configKeyListHead.Flink; + pConfigKey = CONTAINING_RECORD(pListEntry, ConfigKey, listEntry); + + // Free the buffers associated with the ConfigKey + free(pConfigKey->pKeyName); + free(pConfigKey->pValue); + + // Remove the entry from the list + RemoveEntryList(&pConfigKey->listEntry); + + // Finish freeing the ConfigKey + free(pConfigKey); + } + + // Free the rest of the buffers associated with the interface instance data + free(pConfigIfInstance->pConfigFolder); + free(pConfigIfInstance->pConfigName); + free(pConfigIfInstance); + } + + DbgTrace(2, "-ConfigIf_ReleaseReference- End\n", 0); +} + + +//++======================================================================= +char* SSCS_CALL +ConfigIf_GetEntryValue( + IN const void *pIfInstance, + IN const char *pKeyName) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pKeyName - +// Pointer to NULL terminated string that contains the +// name of the key whose value is being requested. +// +// Returns: +// Pointer to NULL terminated string with value being requested or NULL. +// +// Description: +// Gets value associated with a key for the configuration object. +// +// L2 +//=======================================================================-- +{ + ConfigIfInstance *pConfigIfInstance = CONTAINING_RECORD(pIfInstance, ConfigIfInstance, configIf); + char *pValue = NULL; + LIST_ENTRY *pListEntry; + ConfigKey *pConfigKey; + int keyNameLen = (int) strlen(pKeyName); + char *pKeyNameLowercase; + + DbgTrace(2, "-ConfigIf_GetEntryValue- Start\n", 0); + + // Allocate enough space to hold lower case version of the key name + pKeyNameLowercase = (char*) malloc(keyNameLen + 1); + if (pKeyNameLowercase) + { + // Lower case the key name + LowerCaseString(pKeyNameLowercase, pKeyName); + + // Try to find matching ConfigKey + pListEntry = pConfigIfInstance->configKeyListHead.Flink; + while (pListEntry != &pConfigIfInstance->configKeyListHead) + { + // Get pointer to the current entry + pConfigKey = CONTAINING_RECORD(pListEntry, ConfigKey, listEntry); + + // Check if we have a match + if (pConfigKey->keyNameLen == keyNameLen + && memcmp(pKeyNameLowercase, pConfigKey->pKeyName, keyNameLen) == 0) + { + // We found it, return its value. + pValue = (char*) malloc(pConfigKey->valueLen + 1); + if (pValue) + { + strcpy(pValue, pConfigKey->pValue); + } + else + { + DbgTrace(0, "-ConfigIf_GetEntryValue- Buffer allocation failure\n", 0); + } + break; + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Free the lower case version of the key name + free(pKeyNameLowercase); + } + else + { + DbgTrace(0, "-ConfigIf_GetEntryValue- Buffer allocation failure\n", 0); + } + + DbgTrace(2, "-ConfigIf_GetEntryValue- End, pValue = %08X\n", (unsigned int) pValue); + + return pValue; +} + + + +//++======================================================================= +CasaStatus +GetConfigInterface( + IN const char *pConfigFolder, + IN const char *pConfigName, + INOUT ConfigIf **ppConfigIf) +// +// Arguments: +// pConfigFolder - +// Pointer to NULL terminated string that contains the name of +// the folder containing the configuration file. +// +// pConfigName - +// Pointer to NULL terminated string containing the name of the +// configuration entry. +// +// ppConfigIf - +// Pointer to variable that will receive pointer to ConfigIf +// instance. +// +// Returns: +// Casa Status +// +// Description: +// Get configuration interface to specified configuration entry. +// +// L2 +//=======================================================================-- +{ + int configFolderLen = (int) strlen(pConfigFolder); + int configNameLen = (int)strlen(pConfigName); + ConfigIfInstance *pConfigIfInstance; + LIST_ENTRY *pListEntry; + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_INFORMATIONAL, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_OBJECT_NOT_FOUND); + + DbgTrace(2, "-GetConfigInterface- Start\n", 0); + + // Check if we already have an entry in our list for the configuration + pListEntry = g_configIfListHead.Flink; + while (pListEntry != &g_configIfListHead) + { + // Get pointer to the current entry + pConfigIfInstance = CONTAINING_RECORD(pListEntry, ConfigIfInstance, listEntry); + + // Check if we have a match + if (pConfigIfInstance->configFolderLen == configFolderLen + && pConfigIfInstance->configNameLen == configNameLen + && memcmp(pConfigFolder, pConfigIfInstance->pConfigFolder, configFolderLen) == 0 + && memcmp(pConfigName, pConfigIfInstance->pConfigName, configNameLen) == 0) + { + // We found it, return the ConfigIf associated with the instance data + // after incrementing its reference count. + pConfigIfInstance->refCount ++; + *ppConfigIf = &pConfigIfInstance->configIf; + + // Success + retStatus = CASA_STATUS_SUCCESS; + break; + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Proceed to create interface instance data for the configuration if none was found + if (retStatus != CASA_STATUS_SUCCESS) + { + char *pFilePath; + + // Build a string containing the configuration file path + pFilePath = (char*) malloc(configFolderLen + 1 + configNameLen + sizeof(".conf")); + if (pFilePath) + { + FILE *pConfigFile; + + strcpy(pFilePath, pConfigFolder); + strcat(pFilePath, pathCharString); + strcat(pFilePath, pConfigName); + strcat(pFilePath, ".conf"); + + // Open the configuration file for reading + pConfigFile = fopen(pFilePath, "r"); + if (pConfigFile) + { + // Opened the file, create a ConfigIfInstance object for it. + pConfigIfInstance = (ConfigIfInstance*) malloc(sizeof(*pConfigIfInstance)); + if (pConfigIfInstance) + { + // Initialize the list head within the instance data + InitializeListHead(&pConfigIfInstance->configKeyListHead); + + // Initialize the ConfigIf within the instance data + pConfigIfInstance->configIf.addReference = ConfigIf_AddReference; + pConfigIfInstance->configIf.releaseReference = ConfigIf_ReleaseReference; + pConfigIfInstance->configIf.getEntryValue = ConfigIf_GetEntryValue; + + // Save the ConfigFolder and ConfigName information within the instance data + pConfigIfInstance->pConfigFolder = (char*) malloc(configFolderLen + 1); + if (pConfigIfInstance->pConfigFolder) + { + strcpy(pConfigIfInstance->pConfigFolder, pConfigFolder); + pConfigIfInstance->configFolderLen = configFolderLen; + + pConfigIfInstance->pConfigName = (char*) malloc(configNameLen + 1); + if (pConfigIfInstance->pConfigName) + { + strcpy(pConfigIfInstance->pConfigName, pConfigName); + pConfigIfInstance->configNameLen = configNameLen; + + // Add the instance data into our list and bump up its reference count + // since we did that. + InsertTailList(&g_configIfListHead, &pConfigIfInstance->listEntry); + pConfigIfInstance->refCount = 1; + + // At this point we want to return success to the caller even if we + // experience a read error. + retStatus = CASA_STATUS_SUCCESS; + + // Return the ConfigIf associated with the instance data after + // incrementing its reference count. + pConfigIfInstance->refCount ++; + *ppConfigIf = &pConfigIfInstance->configIf; + + // Now update the instance data with the information present in the file + if (fseek(pConfigFile, 0, SEEK_SET) == 0) + { + char line[512]; + + while (fgets(line, sizeof(line), pConfigFile) != NULL) + { + int lineLength; + + RemoveWhiteSpaceFromTheEnd(line); + + lineLength = (int) strlen(line); + if (lineLength != 0) + { + char *pKey; + char *pKeyEnd; + char *pValue; + ConfigKey *pConfigKey; + + // Attempt to find the key + pKey = SkipWhiteSpace(line); + + // Make sure that we are not dealing with an empty line or a comment + if (*pKey == '\0' || *pKey == '#') + continue; + + // Go past the key + pKeyEnd = SkipNonWhiteSpace(pKey); + + // Protect against a malformed line + if (*pKeyEnd == '\0') + { + DbgTrace(0, "-GetConfigInterface- Key found without value\n", 0); + continue; + } + + // Attempt to find the value + pValue = SkipWhiteSpace(pKeyEnd); + + // Protect against a malformed line + if (*pValue == '\0') + { + DbgTrace(0, "-GetConfigInterface- Key found without value\n", 0); + continue; + } + + // Delineate the key + *pKeyEnd = '\0'; + + // Create a ConfigKey object for this key/value pair + pConfigKey = (ConfigKey*) malloc(sizeof(*pConfigKey)); + if (pConfigKey) + { + pConfigKey->keyNameLen = (int) strlen(pKey); + pConfigKey->pKeyName = (char*) malloc(pConfigKey->keyNameLen + 1); + if (pConfigKey->pKeyName) + { + // Save the key name in lower case + LowerCaseString(pConfigKey->pKeyName, pKey); + + pConfigKey->valueLen = (int) strlen(pValue); + pConfigKey->pValue = (char*) malloc(pConfigKey->valueLen + 1); + if (pConfigKey->pValue) + { + strcpy(pConfigKey->pValue, pValue); + + // The entry is ready, now associate it with the instance data. + InsertTailList(&pConfigIfInstance->configKeyListHead, &pConfigKey->listEntry); + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + free(pConfigKey->pKeyName); + free(pConfigKey); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + free(pConfigKey); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + } + } + } + } + else + { + DbgTrace(0, "-GetConfigInterface- File seek error, errno = %d\n", errno); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + + // Free the buffers associated with the instance data + free(pConfigIfInstance->pConfigFolder); + free(pConfigIfInstance); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + + // Free the buffer allocated for the instance data + free(pConfigIfInstance); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation failure\n", 0); + } + + // Close the file + fclose(pConfigFile); + } + else + { + DbgTrace(1, "-GetConfigInterface- Unable to open config file, errno = %d\n", errno); + } + } + else + { + DbgTrace(0, "-GetConfigInterface- Buffer allocation error\n", 0); + } + } + + DbgTrace(2, "-GetConfigInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/auth_token/client/engine.c b/auth_token/client/engine.c new file mode 100644 index 00000000..fcf28fec --- /dev/null +++ b/auth_token/client/engine.c @@ -0,0 +1,626 @@ +/*********************************************************************** + * + * 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 ]================================================== + +#define DEFAULT_RETRY_LIFETIME 5 // seconds + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// +// Debug tracing level +// +int DebugLevel = 0; + +// +// Operating parameter +// +bool secureRpcSetting = false; +int retryLifetime = DEFAULT_RETRY_LIFETIME; + + +//++======================================================================= +static +CasaStatus +ObtainSessionToken( + IN RpcSession *pRpcSession, + IN char *pHostName, + IN AuthPolicy *pAuthPolicy, + INOUT char **ppSessionToken) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + LIST_ENTRY *pListEntry; + AuthCacheEntry *pCacheEntry = NULL; + + DbgTrace(1, "-ObtainSessionToken- Start\n", 0); + + // Initialize output parameter + *ppSessionToken = NULL; + + // Look in our cache for an entry that matches one of the auth + // contexts specified in the AuthPolicy object. + pListEntry = pAuthPolicy->authContextListHead.Flink; + while (pListEntry != &pAuthPolicy->authContextListHead) + { + AuthContext *pAuthContext; + + // Get pointer to AuthContext structure + pAuthContext = CONTAINING_RECORD(pListEntry, AuthContext, listEntry); + + // Try to find a cache entry for the auth context + pCacheEntry = FindEntryInAuthCache(pAuthContext->pContext, pHostName); + if (pCacheEntry != NULL) + { + // Cache entry found, update the return status with the information + // saved in it and stop looking. + retStatus = pCacheEntry->status; + break; + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // If we did not find a cache entry that we can use, then Try to create one. + pListEntry = pAuthPolicy->authContextListHead.Flink; + while (!CASA_SUCCESS(retStatus) + && pListEntry != &pAuthPolicy->authContextListHead) + { + AuthContext *pAuthContext; + char *pAuthMechToken; + + // Get pointer to AuthContext structure + pAuthContext = CONTAINING_RECORD(pListEntry, AuthContext, listEntry); + + // Get authentication mechanism token + retStatus = GetAuthMechToken(pAuthContext, &pAuthMechToken); + if (!CASA_SUCCESS(retStatus)) + { + // We were not able to obtain an authentication mechanism token + // for the context. + // + // Advance to the next entry + pListEntry = pListEntry->Flink; + continue; + } + + // Create a cache entry for the auth context + pCacheEntry = CreateAuthCacheEntry(pAuthContext->pContext, pHostName); + if (pCacheEntry) + { + char *pReqMsg = NULL; + char *pRespMsg = NULL; + int respLen; + int cacheEntryLifetime = retryLifetime; // Initialize to retry in case of failure + + // Request auth token for the service + pReqMsg = BuildAuthenticateMsg(pAuthContext, pAuthMechToken); + if (pReqMsg) + { + // Issue rpc + retStatus = Rpc(pRpcSession, + pAuthContext->pMechanism, + secureRpcSetting, + pReqMsg, + &pRespMsg, + &respLen); + if (CASA_SUCCESS(retStatus)) + { + AuthenticateResp *pAuthenticateResp; + + // Create Authenticate response object + retStatus = CreateAuthenticateResp(pRespMsg, respLen, &pAuthenticateResp); + if (CASA_SUCCESS(retStatus)) + { + // Return the auth token to the caller + pCacheEntry->pToken = pAuthenticateResp->pToken; + pAuthenticateResp->pToken = NULL; // To keep us from freeing the buffer + cacheEntryLifetime = pAuthenticateResp->tokenLifetime; + + // Free the Authenticate response object + RelAuthenticateResp(pAuthenticateResp); + } + } + else + { + DbgTrace(0, "-ObtainSessionToken- Authenticate Rpc failure, error = %08X\n", retStatus); + } + } + else + { + DbgTrace(0, "-ObtainSessionToken- Error building Authenticate msg\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Add the entry to the cache if successful or if the reason that we failed + // was because the server was unavailable. + if (CASA_SUCCESS(retStatus) + || CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE) + { + pCacheEntry->status = retStatus; + AddEntryToAuthCache(pCacheEntry, cacheEntryLifetime); + } + else + { + // Free the entry + FreeAuthCacheEntry(pCacheEntry); + } + } + else + { + DbgTrace(0, "-ObtainSessionToken- Cache entry creation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + + // Stop trying after freeing up the buffer associated with + // the authentication mechanism token. + free(pAuthMechToken); + break; + } + + // Free up the buffer associated with the authentication mechanism token + free(pAuthMechToken); + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Return session token if successful + if (CASA_SUCCESS(retStatus)) + { + // Allocate a buffer for the return token + *ppSessionToken = (char*) malloc(strlen(pCacheEntry->pToken) + 1); + if (*ppSessionToken) + { + // Copy the token onto the allocated buffer + strcpy(*ppSessionToken, pCacheEntry->pToken); + } + else + { + DbgTrace(0, "-ObtainSessionToken- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + + DbgTrace(1, "-ObtainSessionToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +static +CasaStatus +ObtainAuthTokenFromServer( + IN char *pServiceName, + IN char *pHostName, + INOUT char **ppAuthToken, + INOUT int *pTokenLifetime) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + RpcSession *pRpcSession; + + DbgTrace(1, "-ObtainAuthTokenFromServer- Start\n", 0); + + // Initialize output parameter + *ppAuthToken = NULL; + + // Open Rpc Session to the auth service at the specified host + pRpcSession = OpenRpcSession(pHostName); + if (pRpcSession) + { + char *pReqMsg = NULL; + char *pRespMsg = NULL; + int respLen; + AuthPolicy *pAuthPolicy = NULL; + GetAuthPolicyResp *pGetAuthPolicyResp = NULL; + GetAuthTokenResp *pGetAuthTokenResp = NULL; + char *pSessionToken = NULL; + + // Request the auth parameters associated with this service + pReqMsg = BuildGetAuthPolicyMsg(pServiceName, pHostName); + if (pReqMsg) + { + // Issue rpc + retStatus = Rpc(pRpcSession, + "GetAuthPolicy", + secureRpcSetting, + pReqMsg, + &pRespMsg, + &respLen); + if (CASA_SUCCESS(retStatus)) + { + // Create GetAuthPolicy response object + retStatus = CreateGetAuthPolicyResp(pRespMsg, respLen, &pGetAuthPolicyResp); + if (CASA_SUCCESS(retStatus)) + { + // Create the AuthPolicy object + retStatus = CreateAuthPolicy(pGetAuthPolicyResp->pPolicy, + pGetAuthPolicyResp->policyLen, + &pAuthPolicy); + if (CASA_SUCCESS(retStatus)) + { + // Now try to obtain a session token + retStatus = ObtainSessionToken(pRpcSession, pHostName, pAuthPolicy, &pSessionToken); + if (CASA_SUCCESS(retStatus)) + { + // Request auth token for the service + free(pReqMsg); + pReqMsg = BuildGetAuthTokenMsg(pServiceName, pHostName, pSessionToken); + if (pReqMsg) + { + // Free the previous response msg buffer + free(pRespMsg); + pRespMsg = NULL; + + // Issue rpc + retStatus = Rpc(pRpcSession, + "GetAuthToken", + secureRpcSetting, + pReqMsg, + &pRespMsg, + &respLen); + if (CASA_SUCCESS(retStatus)) + { + // Create GetAuthPolicy response object + retStatus = CreateGetAuthTokenResp(pRespMsg, respLen, &pGetAuthTokenResp); + if (CASA_SUCCESS(retStatus)) + { + // Return the auth token to the caller + *ppAuthToken = pGetAuthTokenResp->pToken; + pGetAuthTokenResp->pToken = NULL; // To keep us from freeing the buffer + *pTokenLifetime = pGetAuthTokenResp->tokenLifetime; + } + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- GetAuthToken Rpc failure, error = %08X\n", retStatus); + } + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- Error building GetAuthToken msg\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + DbgTrace(1, "-ObtainAuthTokenFromServer- Failed to obtain session token, error = %08X\n", retStatus); + } + } + } + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- GetAuthPolicy Rpc failure, error = %08X\n", retStatus); + } + + // Free resources that may be hanging around + if (pReqMsg) + free(pReqMsg); + + if (pRespMsg) + free(pRespMsg); + + if (pSessionToken) + free(pSessionToken); + + if (pGetAuthTokenResp) + RelGetAuthTokenResp(pGetAuthTokenResp); + + if (pGetAuthPolicyResp) + RelGetAuthPolicyResp(pGetAuthPolicyResp); + + if (pAuthPolicy) + RelAuthPolicy(pAuthPolicy); + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- Error building GetAuthPolicy msg\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Close the Rpc Session + CloseRpcSession(pRpcSession); + } + else + { + DbgTrace(0, "-ObtainAuthTokenFromServer- Error opening Rpc session\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(1, "-ObtainAuthTokenFromServer- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus SSCS_CALL +ObtainAuthToken( + IN const char *pServiceAtHostName, + INOUT char *pAuthTokenBuf, + INOUT int *pAuthTokenBufLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + char *pParseString; + + DbgTrace(1, "-ObtainAuthToken- Start\n", 0); + + // Verify the input parameters + if (pServiceAtHostName == NULL + || pAuthTokenBufLen == NULL + || (*pAuthTokenBufLen != 0 && pAuthTokenBuf == NULL)) + { + DbgTrace(0, "-ObtainAuthToken- Invalid parameter\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Allocate space to copy the service name string + pParseString = (char*) malloc(strlen(pServiceAtHostName) + 1); + if (pParseString) + { + char *pServiceName, *pHostName; + + // Space allocated, now copy the string onto it + // and parse it into its components. + strcpy(pParseString, pServiceAtHostName); + pServiceName = strtok(pParseString, "@"); + pHostName = strtok(NULL, "@"); + if (pHostName == NULL) + { + DbgTrace(0, "-ObtainAuthToken- Missing host name\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INVALID_PARAMETER); + } + else + { + AuthCacheEntry *pCacheEntry; + char *pNormalizedHostName; + + printf("Obtaining auth token for Service = %s at Host = %s", pServiceName, pHostName); + + // Normalize the host name + pNormalizedHostName = NormalizeHostName(pHostName); + if (pNormalizedHostName) + { + // Start user process synchronization + LockUserMutex(); + + // Try to find a cache entry for the service + pCacheEntry = FindEntryInAuthCache(pServiceName, pNormalizedHostName); + if (pCacheEntry == NULL) + { + // No entry found in the cache, create one. + pCacheEntry = CreateAuthCacheEntry(pServiceName, pNormalizedHostName); + if (pCacheEntry) + { + int cacheEntryLifetime = retryLifetime; // Initialize to retry in case of failure + + // Cache entry created, now try to obtain auth token from the CASA Server + retStatus = ObtainAuthTokenFromServer(pServiceName, + pNormalizedHostName, + &pCacheEntry->pToken, + &cacheEntryLifetime); + + // Add the entry to the cache if successful or if the reason that we failed + // was because the server was un-available. + if (CASA_SUCCESS(retStatus) + || CasaStatusCode(retStatus) == CASA_STATUS_AUTH_SERVER_UNAVAILABLE) + { + pCacheEntry->status = retStatus; + AddEntryToAuthCache(pCacheEntry, cacheEntryLifetime); + } + else + { + // Free the entry + FreeAuthCacheEntry(pCacheEntry); + } + } + else + { + DbgTrace(0, "-ObtainAuthToken- Cache entry creation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + // Cache entry found, update the return status with the information saved in it. + retStatus = pCacheEntry->status; + } + + // Try to return auth token if we have one to return + if (CASA_SUCCESS(retStatus)) + { + int tokenLen = (int) strlen(pCacheEntry->pToken) + 1; + + // We have an authentication token, try to return it to the caller. + if (pAuthTokenBuf) + { + // Verify that the supplied buffer is big enough + if (*pAuthTokenBufLen >= tokenLen) + { + // Return the auth token to the caller + strcpy(pAuthTokenBuf, pCacheEntry->pToken); + } + else + { + DbgTrace(0, "-ObtainAuthToken- The supplied buffer is not large enough", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + + // Notify the caller about the token length + *pAuthTokenBufLen = tokenLen; + } + else + { + // The caller just wants the length of buffer that is required to + // obtain the token. + *pAuthTokenBufLen = tokenLen; + } + } + + // Stop user process synchronization + FreeUserMutex(); + + // Free the space allocated for the normalized host name + free(pNormalizedHostName); + } + else + { + DbgTrace(0, "-ObtainAuthToken- Host name normalization failed\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + + // Free allocated space + free(pParseString); + } + else + { + DbgTrace(0, "-ObtainAuthToken- Buffer allocation error\n", 0); + } + +exit: + + DbgTrace(1, "-ObtainAuthToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +int +InitializeLibrary(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + int retStatus = -1; + + DbgTrace(1, "-InitializeLibrary- Start\n", 0); + + // Create user synchronization mutex + if (CreateUserMutex() == 0) + { + // Initialize the auth cache + if (CASA_SUCCESS(InitializeAuthCache())) + { + // Initialize the host name normalization + if (CASA_SUCCESS(InitializeHostNameNormalization())) + { + // Success + retStatus = 0; + } + else + { + DbgTrace(0, "-InitializeLibrary- Error initializing host name normalization\n", 0); + } + } + else + { + DbgTrace(0, "-InitializeLibrary- Error initializing the auth cache\n", 0); + } + } + else + { + DbgTrace(0, "-InitializeLibrary- Error creating mutex for the user\n", 0); + } + + DbgTrace(1, "-InitializeLibrary- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + diff --git a/auth_token/client/getpolicymsg.c b/auth_token/client/getpolicymsg.c new file mode 100644 index 00000000..51a0821d --- /dev/null +++ b/auth_token/client/getpolicymsg.c @@ -0,0 +1,1309 @@ +/*********************************************************************** + * + * 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); +} + diff --git a/auth_token/client/gettokenmsg.c b/auth_token/client/gettokenmsg.c new file mode 100644 index 00000000..438feee5 --- /dev/null +++ b/auth_token/client/gettokenmsg.c @@ -0,0 +1,736 @@ +/*********************************************************************** + * + * 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_LIFETIME_DATA 0x8 +#define AWAITING_LIFETIME_ELEMENT_START 0x9 +#define AWAITING_LIFETIME_ELEMENT_END 0xA +#define AWAITING_AUTH_TOKEN_ELEMENT_START 0xB +#define AWAITING_AUTH_TOKEN_ELEMENT_END 0xC +#define AWAITING_AUTH_TOKEN_DATA 0xD +#define DONE_PARSING 0xE + +// +// Get Authentication Token Response Parse Structure +// +typedef struct _GetAuthTokenRespParse +{ + XML_Parser p; + int state; + int tokenDataProcessed; + GetAuthTokenResp *pGetAuthTokenResp; + CasaStatus status; + +} GetAuthTokenRespParse, *PGetAuthTokenRespParse; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//++======================================================================= +char* +BuildGetAuthTokenMsg( + IN char *pServiceName, + IN char *pHostName, + IN char *pSessionToken) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + char *pMsg = NULL; + int bufferSize; + + DbgTrace(1, "-BuildGetAuthTokenMsg- Start\n", 0); + + /* + * The format of the get authentication token request message + * is as follows: + * + * + * + * service name + * host name + * session token data + * + * + */ + + // Determine the buffer size necessary to hold the msg + bufferSize = strlen(XML_DECLARATION) + + 2 // crlf + + 1 // < + + strlen(GET_AUTH_TOKEN_REQUEST_ELEMENT_NAME) + + 3 // >crlf + + 1 // < + + strlen(SERVICE_ELEMENT_NAME) + + 1 // > + + strlen(pServiceName) + + 2 // crlf + + 2 // + + strlen(pHostName) + + 2 // crlf + + 2 // + + strlen(pSessionToken) + + 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_TOKEN_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, "<"); + strcat(pMsg, SESSION_TOKEN_ELEMENT_NAME); + strcat(pMsg, ">"); + strcat(pMsg, pSessionToken); + strcat(pMsg, "\r\n"); + strcat(pMsg, ""); + } + else + { + DbgTrace(0, "-BuildGetAuthTokenMsg- Buffer allocation error\n", 0); + } + + DbgTrace(1, "-BuildGetAuthTokenMsg- End, pMsg = %08X\n", pMsg); + + return pMsg; +} + + +//++======================================================================= +static +void XMLCALL +GetAuthTokenRespStartElementHandler( + IN GetAuthTokenRespParse *pGetAuthTokenRespParse, + IN const XML_Char *name, + IN const XML_Char **atts) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + DbgTrace(2, "-GetAuthTokenRespStartElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pGetAuthTokenRespParse->state) + { + case AWAITING_ROOT_ELEMENT_START: + + // In this state, we are only expecting the Get Authentication + // Token Response Element. + if (strcmp(name, GET_AUTH_TOKEN_RESPONSE_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_STATUS_ELEMENT_START; + } + else + { + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->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. + pGetAuthTokenRespParse->state = AWAITING_DESCRIPTION_ELEMENT_START; + } + else + { + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->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. + pGetAuthTokenRespParse->state = AWAITING_DESCRIPTION_DATA; + } + else + { + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_AUTH_TOKEN_ELEMENT_START: + + // In this state, we are only expecting the Authentication Token Element. + if (strcmp(name, AUTH_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_LIFETIME_ELEMENT_START; + } + else + { + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_LIFETIME_ELEMENT_START: + + // In this state, we are only expecting the Lifetime Element. + if (strcmp(name, LIFETIME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_LIFETIME_DATA; + } + else + { + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-GetAuthTokenRespStartElementHandler- Un-expected state = %d\n", pGetAuthTokenRespParse->state); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-GetAuthTokenRespStartElementHandler- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +GetAuthTokenRespCharDataHandler( + IN GetAuthTokenRespParse *pGetAuthTokenRespParse, + IN const XML_Char *s, + IN int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + DbgTrace(2, "-GetAuthTokenRespCharDataHandler- 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 (pGetAuthTokenRespParse->state) + { + case AWAITING_DESCRIPTION_DATA: + + // Ignore the status description data for now. + + // Advanced to the next state + pGetAuthTokenRespParse->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) + { + pGetAuthTokenRespParse->status = CASA_STATUS_SUCCESS; + } + else if (strncmp(HTTP_UNAUTHORIZED_STATUS_CODE, s, len) == 0) + { + pGetAuthTokenRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_AUTHENTICATION_FAILURE); + } + else if (strncmp(HTTP_SERVER_ERROR_STATUS_CODE, s, len) == 0) + { + pGetAuthTokenRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_SERVER_ERROR); + } + else + { + DbgTrace(0, "-GetAuthTokenRespCharDataHandler- Un-expected status\n", 0); + pGetAuthTokenRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Advanced to the next state + pGetAuthTokenRespParse->state = AWAITING_STATUS_ELEMENT_END; + break; + + case AWAITING_LIFETIME_DATA: + + // Convert the lifetime string to a numeric value + pGetAuthTokenRespParse->pGetAuthTokenResp->tokenLifetime = dtoul(s, len); + + // Advanced to the next state + pGetAuthTokenRespParse->state = AWAITING_LIFETIME_ELEMENT_END; + break; + + case AWAITING_AUTH_TOKEN_DATA: + case AWAITING_AUTH_TOKEN_ELEMENT_END: + + // Check if we have already processed token data + if (pGetAuthTokenRespParse->tokenDataProcessed == 0) + { + // Keep a copy of the authentication token (null terminated) + pGetAuthTokenRespParse->pGetAuthTokenResp->pToken = (char*) malloc(len + 1); + if (pGetAuthTokenRespParse->pGetAuthTokenResp->pToken) + { + memset(pGetAuthTokenRespParse->pGetAuthTokenResp->pToken, 0, len + 1); + memcpy(pGetAuthTokenRespParse->pGetAuthTokenResp->pToken, s, len); + pGetAuthTokenRespParse->tokenDataProcessed = len; + + // Advanced to the next state + pGetAuthTokenRespParse->state = AWAITING_AUTH_TOKEN_ELEMENT_END; + } + else + { + DbgTrace(0, "-GetAuthTokenRespCharDataHandler- Buffer allocation failure\n", 0); + pGetAuthTokenRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + } + else + { + char *pNewBuf; + + // We have already received token data, append this data to it. + pNewBuf = (char*) malloc(pGetAuthTokenRespParse->tokenDataProcessed + len + 1); + if (pNewBuf) + { + memset(pNewBuf, + 0, + pGetAuthTokenRespParse->tokenDataProcessed + len + 1); + memcpy(pNewBuf, + pGetAuthTokenRespParse->pGetAuthTokenResp->pToken, + pGetAuthTokenRespParse->tokenDataProcessed); + memcpy(pNewBuf + pGetAuthTokenRespParse->tokenDataProcessed, s, len); + pGetAuthTokenRespParse->tokenDataProcessed += len; + + // Swap the buffers + free(pGetAuthTokenRespParse->pGetAuthTokenResp->pToken); + pGetAuthTokenRespParse->pGetAuthTokenResp->pToken = pNewBuf; + } + else + { + DbgTrace(0, "-GetAuthTokenRespCharDataHandler- Buffer allocation failure\n", 0); + pGetAuthTokenRespParse->status = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + } + break; + + default: + DbgTrace(0, "-GetAuthTokenRespCharDataHandler- Un-expected state = %d\n", pGetAuthTokenRespParse->state); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + break; + } + +exit: + + DbgTrace(2, "-GetAuthTokenRespCharDataHandler- End\n", 0); +} + + +//++======================================================================= +static +void XMLCALL +GetAuthTokenRespEndElementHandler( + IN GetAuthTokenRespParse *pGetAuthTokenRespParse, + IN const XML_Char *name) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + DbgTrace(2, "-GetAuthTokenRespEndElementHandler- Start\n", 0); + + // Proceed based on the state + switch (pGetAuthTokenRespParse->state) + { + case AWAITING_ROOT_ELEMENT_END: + + // In this state, we are only expecting the Get Authentication + // Token Response Element. + if (strcmp(name, GET_AUTH_TOKEN_RESPONSE_ELEMENT_NAME) == 0) + { + // Done. + pGetAuthTokenRespParse->state = DONE_PARSING; + } + else + { + DbgTrace(0, "-GetAuthTokenRespEndHandler- Un-expected end element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->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. + pGetAuthTokenRespParse->state = AWAITING_STATUS_DATA; + } + else + { + DbgTrace(0, "-GetAuthTokenRespEndElementHandler- Un-expected end element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->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(pGetAuthTokenRespParse->status)) + { + // The request completed successfully + pGetAuthTokenRespParse->state = AWAITING_AUTH_TOKEN_ELEMENT_START; + } + else + { + pGetAuthTokenRespParse->state = AWAITING_ROOT_ELEMENT_END; + } + } + else + { + DbgTrace(0, "-GetAuthTokenRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_LIFETIME_ELEMENT_END: + + // In this state, we are only expecting the Lifetime Element. + if (strcmp(name, LIFETIME_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_AUTH_TOKEN_DATA; + } + else + { + DbgTrace(0, "-GetAuthTokenRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + case AWAITING_AUTH_TOKEN_ELEMENT_END: + + // In this state, we are only expecting the Authentication Token Element. + if (strcmp(name, AUTH_TOKEN_ELEMENT_NAME) == 0) + { + // Good, advance to the next state. + pGetAuthTokenRespParse->state = AWAITING_ROOT_ELEMENT_END; + } + else + { + DbgTrace(0, "-GetAuthTokenRespEndElementHandler- Un-expected start element\n", 0); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + } + break; + + default: + DbgTrace(0, "-GetAuthTokenRespEndElementHandler- Un-expected state = %d\n", pGetAuthTokenRespParse->state); + XML_StopParser(pGetAuthTokenRespParse->p, XML_FALSE); + break; + } + + DbgTrace(2, "-GetAuthTokenRespEndElementHandler- End\n", 0); +} + + +//++======================================================================= +CasaStatus +CreateGetAuthTokenResp( + IN char *pRespMsg, + IN int respLen, + INOUT GetAuthTokenResp **ppGetAuthTokenResp) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + GetAuthTokenRespParse getAuthTokenRespParse = {0}; + GetAuthTokenResp *pGetAuthTokenResp; + + DbgTrace(1, "-CreateGetAuthTokenResp- Start\n", 0); + + /* + * When a get authentication token request is processed successfully, the + * server replies to the client with a message with the following format: + * + * + * + * ok200 + * lifetime valuesession token data + * + * + * When a get authentication token 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 GetAuthTokenResp object + pGetAuthTokenResp = malloc(sizeof(*pGetAuthTokenResp)); + if (pGetAuthTokenResp) + { + XML_Parser p; + + // Initialize the GetAuthTokenResp object and set it in the + // parse oject. + memset(pGetAuthTokenResp, 0, sizeof(*pGetAuthTokenResp)); + getAuthTokenRespParse.pGetAuthTokenResp = pGetAuthTokenResp; + + // Create parser + p = XML_ParserCreate(NULL); + if (p) + { + // Keep track of the parser in our parse object + getAuthTokenRespParse.p = p; + + // Initialize the status within the parse object + getAuthTokenRespParse.status = CASA_STATUS_SUCCESS; + + // Set the start and end element handlers + XML_SetElementHandler(p, + GetAuthTokenRespStartElementHandler, + GetAuthTokenRespEndElementHandler); + + // Set the character data handler + XML_SetCharacterDataHandler(p, GetAuthTokenRespCharDataHandler); + + + // Set our user data + XML_SetUserData(p, &getAuthTokenRespParse); + + // Parse the document + if (XML_Parse(p, pRespMsg, respLen, 1) == XML_STATUS_OK) + { + // Verify that the parse operation completed successfully + if (getAuthTokenRespParse.state == DONE_PARSING) + { + // The parse operation succeded, obtain the status returned + // by the server. + retStatus = getAuthTokenRespParse.status; + } + else + { + DbgTrace(0, "-CreateGetAuthTokenResp- Parse operation did not complete\n", 0); + + // Check if a status has been recorded + if (getAuthTokenRespParse.status != CASA_STATUS_SUCCESS) + { + retStatus = getAuthTokenRespParse.status; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_PROTOCOL_ERROR); + } + } + } + else + { + DbgTrace(0, "-CreateGetAuthTokenResp- 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, "-CreateGetAuthTokenResp- 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)) + { + *ppGetAuthTokenResp = pGetAuthTokenResp; + } + else + { + free(pGetAuthTokenResp); + } + } + else + { + DbgTrace(0, "-CreateGetAuthTokenResp- Memory allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + DbgTrace(1, "-CreateGetAuthTokenResp- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +RelGetAuthTokenResp( + IN GetAuthTokenResp *pGetAuthTokenResp) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + DbgTrace(1, "-RelGetAuthTokenResp- Start\n", 0); + + // Free the resources associated with the object + if (pGetAuthTokenResp->pToken) + free(pGetAuthTokenResp->pToken); + + free(pGetAuthTokenResp); + + DbgTrace(1, "-RelGetAuthTokenResp- End\n", 0); +} + diff --git a/auth_token/client/internal.h b/auth_token/client/internal.h new file mode 100644 index 00000000..c01bd9f0 --- /dev/null +++ b/auth_token/client/internal.h @@ -0,0 +1,345 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +//===[ Include files ]===================================================== + +#include "platform.h" +#include +#include +#include +#include +#include "list_entry.h" +#include "mech_if.h" +#include "proto.h" + +//===[ Type definitions ]================================================== + +// +// Authentication Context structure +// +typedef struct _AuthContext +{ + LIST_ENTRY listEntry; + char *pContext; + char *pMechanism; + char *pMechInfo; + +} AuthContext, *PAuthContext; + +// +// Authentication Policy structure +// +typedef struct _AuthPolicy +{ + LIST_ENTRY authContextListHead; + +} AuthPolicy, *PAuthPolicy; + +// +// Get Authentication Policy Response structure +// +typedef struct _GetAuthPolicyResp +{ + char *pPolicy; + int policyLen; + +} GetAuthPolicyResp, *PGetAuthPolicyResp; + +// +// Get Authentication Token Response structure +// +typedef struct _GetAuthTokenResp +{ + char *pToken; + int tokenLifetime; + +} GetAuthTokenResp, *PGetAuthTokenResp; + +// +// Authenticate Response structure +// +typedef struct _AuthenticateResp +{ + char *pToken; + int tokenLifetime; + +} AuthenticateResp, *PAuthenticateResp; + + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Global externals ]================================================== + +extern int DebugLevel; + +extern char mechConfigFolder[]; + +extern char pathCharString[]; + + + +//===[ External prototypes ]=============================================== + +// +// Functions exported by engine.c +// + +extern +int +InitializeLibrary(void); + +// +// Functions exported by authmech.c +// + +extern +CasaStatus +GetAuthMechToken( + IN AuthContext *pAuthContext, + INOUT char **ppAuthMechToken); + +// +// Functions exported by getpolicymsg.c +// + +extern +CasaStatus +CreateAuthPolicy( + IN char *pEncodedData, + IN int encodedDataLen, + INOUT AuthPolicy **ppAuthPolicy); + +extern +void +RelAuthPolicy( + IN AuthPolicy *pAuthPolicy); + +extern +char* +BuildGetAuthPolicyMsg( + IN char *pServiceName, + IN char *pHostName); + +extern +CasaStatus +CreateGetAuthPolicyResp( + IN char *pRespMsg, + IN int respLen, + INOUT GetAuthPolicyResp **ppGetAuthPolicyResp); + +extern +void +RelGetAuthPolicyResp( + IN GetAuthPolicyResp *pGetAuthPolicyResp); + +// +// Functions exported by authmsg.c +// + +extern +char* +BuildAuthenticateMsg( + IN AuthContext *pAuthContext, + IN char *pAuthMechToken); + +extern +CasaStatus +CreateAuthenticateResp( + IN char *pRespMsg, + IN int respLen, + INOUT AuthenticateResp **ppAuthenticateResp); + +extern +void +RelAuthenticateResp( + IN AuthenticateResp *pAuthenticateResp); + +// +// Functions exported by gettokenmsg.c +// + +extern +char* +BuildGetAuthTokenMsg( + IN char *pServiceName, + IN char *pHostName, + IN char *pSessionToken); + +extern +CasaStatus +CreateGetAuthTokenResp( + IN char *pRespMsg, + IN int respLen, + INOUT GetAuthTokenResp **ppGetAuthTokenResp); + +extern +void +RelGetAuthTokenResp( + IN GetAuthTokenResp *pGetAuthTokenResp); + +// +// Functions exported by cache.c +// + +extern +AuthCacheEntry* +CreateAuthCacheEntry( + IN char *pCacheKey, + IN char *pHostName); + +extern +void +FreeAuthCacheEntry( + IN AuthCacheEntry *pEntry); + +extern +AuthCacheEntry* +FindEntryInAuthCache( + IN char *pCacheKey, + IN char *pHostName); + +extern +void +AddEntryToAuthCache( + IN AuthCacheEntry *pEntry, + IN int entryLifetime); + +extern +CasaStatus +InitializeAuthCache(void); + +// +// Functions exported by config.c +// + +extern +CasaStatus +GetConfigInterface( + IN const char *pConfigFolder, + IN const char *pConfigName, + INOUT ConfigIf **ppConfigIf); + +// +// Functions exported by platutils.c +// + +extern +CasaStatus +CreateUserMutex(void); + +extern +void +LockUserMutex(void); + +extern +void +FreeUserMutex(void); + +extern +LIB_HANDLE +OpenLibrary( + IN char *pFileName); + +extern +void +CloseLibrary( + IN LIB_HANDLE libHandle); + +extern +void* +GetFunctionPtr( + IN LIB_HANDLE libHandle, + IN char *pFunctionName); + +extern +char* +NormalizeHostName( + IN char *pHostName); + +extern +CasaStatus +InitializeHostNameNormalization(void); + +// +// Functions exported by rpc.c +// + +extern +RpcSession* +OpenRpcSession( + IN char *pHostName); + +extern +void +CloseRpcSession( + IN RpcSession *pSession); + +extern +CasaStatus +Rpc( + IN RpcSession *pSession, + IN char *pMethod, + IN bool secure, + IN char *pRequestData, + INOUT char **ppResponseData, + INOUT int *pResponseDataLen); + +// +// Defined in utils.c +// + +extern +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen); + +extern +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen); + +extern +int +dtoul( + IN char *cp, + IN int len); + + +//========================================================================= + +#endif // _INTERNAL_H_ + diff --git a/auth_token/client/list_entry.h b/auth_token/client/list_entry.h new file mode 100644 index 00000000..42aaa926 --- /dev/null +++ b/auth_token/client/list_entry.h @@ -0,0 +1,186 @@ +/*********************************************************************** + * + * Copyright (C) 2005-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. + * + ***********************************************************************/ + +#ifndef _LIST_ENTRY_H_ +#define _LIST_ENTRY_H_ + +#if defined(__cplusplus) || defined(c_plusplus) +extern "C" +{ +#endif + +//===[ Include files ]===================================================== + +//#include + +//===[ Type definitions ]================================================== + +#ifndef CSAPI +#if defined(WIN32) +#define CSAPI __stdcall +#else +#define CSAPI +#endif +#endif + +#ifndef IN +#define IN +#endif + +#ifndef OUT +#define OUT +#endif + +#ifndef INOUT +#define INOUT +#endif + +// +// LIST_ENTRY Type +// Doubly linked list structure +// +//typedef struct _LIST_ENTRY +//{ +// struct _LIST_ENTRY * volatile Flink; +// struct _LIST_ENTRY * volatile Blink; +//} LIST_ENTRY, *PLIST_ENTRY; + + +//===[ Inlines functions ]=============================================== + +// +// Inline functions for operating on LIST_ENTRY double-linked lists +// + +__inline static void InitializeListHead( + IN PLIST_ENTRY pListEntry ) +{ + pListEntry->Flink = pListEntry->Blink = pListEntry; +} + +__inline static void InsertEntryAfter( + IN PLIST_ENTRY pListEntry, + IN PLIST_ENTRY pAfterEntry ) +{ + pListEntry->Flink = pAfterEntry->Flink; + pListEntry->Blink = pAfterEntry; + pListEntry->Flink->Blink = pAfterEntry->Flink = pListEntry; +} + +__inline static void InsertEntryBefore( + IN PLIST_ENTRY pListEntry, + IN PLIST_ENTRY pBeforeEntry ) +{ + pListEntry->Flink = pBeforeEntry; + pListEntry->Blink = pBeforeEntry->Blink; + pListEntry->Blink->Flink = pBeforeEntry->Blink = pListEntry; +} + +__inline static void InsertHeadList( + IN PLIST_ENTRY pListHead, + IN PLIST_ENTRY pListEntry ) +{ + pListEntry->Blink = pListHead; + pListEntry->Flink = pListHead->Flink; + pListEntry->Flink->Blink = pListHead->Flink = pListEntry; +} + +__inline static void InsertTailList( + IN PLIST_ENTRY pListHead, + IN PLIST_ENTRY pListEntry ) +{ + pListEntry->Flink = pListHead; + pListEntry->Blink = pListHead->Blink; + pListEntry->Blink->Flink = pListHead->Blink = pListEntry; +} + +__inline static bool IsListEmpty( + IN PLIST_ENTRY pListHead ) +{ + bool rc = false; + if(pListHead->Flink == pListHead) + rc = true; + return(rc); +} + +__inline static void RemoveEntryList( + IN PLIST_ENTRY pListEntry ) +{ + pListEntry->Flink->Blink = pListEntry->Blink; + pListEntry->Blink->Flink = pListEntry->Flink; + pListEntry->Flink = pListEntry->Blink = (PLIST_ENTRY) 0xbaadf00d; +} + +__inline static PLIST_ENTRY RemoveHeadList( + IN PLIST_ENTRY pListHead ) +{ + PLIST_ENTRY Entry = (PLIST_ENTRY)0; + if(pListHead->Flink != pListHead) + { + Entry = pListHead->Flink; + RemoveEntryList(Entry); + } + return(Entry); +} + +__inline static PLIST_ENTRY RemoveTailList( + IN PLIST_ENTRY pListHead ) +{ + PLIST_ENTRY Entry= (PLIST_ENTRY)0; + if(pListHead->Blink != pListHead) + { + Entry = pListHead->Blink; + RemoveEntryList(Entry); + } + return(Entry); +} + +__inline static PLIST_ENTRY GetFirstListEntry( + IN PLIST_ENTRY pList) +{ + PLIST_ENTRY Entry = (PLIST_ENTRY)0; + if(pList != pList->Flink) + Entry = pList->Flink; + return(Entry); +} + +__inline static PLIST_ENTRY GetNextListEntry( + IN PLIST_ENTRY pList, + IN PLIST_ENTRY pEntry) +{ + PLIST_ENTRY Entry = (PLIST_ENTRY)0; + if(pList != pEntry->Flink) + Entry = pEntry->Flink; + return(Entry); +} + + +//========================================================================= + + +#if defined(__cplusplus) || defined(c_plusplus) +} +#endif // #if defined(__cplusplus) || defined(c_plusplus) + +#endif // #ifndef _LIST_ENTRY_H_ + + diff --git a/auth_token/client/mech_if.h b/auth_token/client/mech_if.h new file mode 100644 index 00000000..346cec6e --- /dev/null +++ b/auth_token/client/mech_if.h @@ -0,0 +1,232 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + + +#ifndef _MECH_IF_H_ +#define _MECH_IF_H_ + + +//===[ Include files ]===================================================== + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +/************************************************************************** +*************************************************************************** +** ** +** Definitions common to all interfaces ** +** ** +*************************************************************************** +**************************************************************************/ + + +//++======================================================================= +typedef +int +(SSCS_CALL *PFN_AddReference)( + IN const void *pIfInstance); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +//=======================================================================-- + + +//++======================================================================= +typedef +void +(SSCS_CALL *PFN_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. +//=======================================================================-- + + + +/************************************************************************** +*************************************************************************** +** ** +** Configuration Object Interface Definitions ** +** ** +*************************************************************************** +**************************************************************************/ + + +//++======================================================================= +typedef +char* +(SSCS_CALL *PFN_GetEntryValue)( + IN const void *pIfInstance, + IN const char *pKeyName); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pKeyName - +// Pointer to NULL terminated string that contains the +// name of the key whose value is being requested. +// +// Returns: +// Pointer to NULL terminated string with value being requested or NULL. +// +// Description: +// Gets value associated with a key for the configuration object. +//=======================================================================-- + + +// +// Config Interface Object +// +typedef struct _ConfigIf +{ + PFN_AddReference addReference; + PFN_ReleaseReference releaseReference; + PFN_GetEntryValue getEntryValue; + +} ConfigIf, *PConfigIf; + + + +/************************************************************************** +*************************************************************************** +** ** +** Authentication Mechanism Token Interface Definitions ** +** ** +*************************************************************************** +**************************************************************************/ + + +//++======================================================================= +typedef +CasaStatus +(SSCS_CALL *PFN_GetAuthToken)( + IN const void *pIfInstance, + IN const char *pContext, + IN const char *pMechInfo, + INOUT char *pTokenBuf, + INOUT int *pTokenBufLen); +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pServiceConfigIf - +// Pointer to service config object to which the client is trying to +// authenticate. +// +// pContext - +// Pointer to null terminated string containing mechanism specific +// context information. Another name for context is Authentication +// Realm. +// +// pMechInfo - +// Pointer to null terminated string containing mechanism specific +// information. This is information is provided by the server to +// aid the mechanism to generate an authentication token. For +// example, the mechanism information for a Kerberos mechanism +// may be the service principal name to which the user will be +// authenticating. +// +// pTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pUserNameBuf is +// not large enough. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified service. +//=======================================================================-- + + +// +// AuthMechToken Interface Object +// +typedef struct _AuthTokenIf +{ + PFN_AddReference addReference; + PFN_ReleaseReference releaseReference; + PFN_GetAuthToken getAuthToken; + +} AuthTokenIf, *PAuthTokenIf; + + +//++======================================================================= +typedef +CasaStatus +(SSCS_CALL *PFN_GetAuthTokenIfRtn)( + IN const ConfigIf *pModuleConfigIf, + INOUT AuthTokenIf **ppAuthTokenIf); +// +// Arguments: +// pModuleConfigIf - +// Pointer to configuration interface instance for the module. +// +// ppAuthTokenIf - +// Pointer to variable that will receive pointer to AuthTokenIf +// instance. +// +// Returns: +// Casa Status +// +// Description: +// Gets authentication token interface instance. +//=======================================================================-- + +#define GET_AUTH_TOKEN_INTERFACE_RTN_SYMBOL "GetAuthTokenInterface" +#define GET_AUTH_TOKEN_INTERFACE_RTN GetAuthTokenInterface + + +#endif // #ifndef _MECH_IF_H_ + diff --git a/auth_token/client/mechanisms/krb5/Krb5Authenticate.conf b/auth_token/client/mechanisms/krb5/Krb5Authenticate.conf new file mode 100644 index 00000000..df843e9f --- /dev/null +++ b/auth_token/client/mechanisms/krb5/Krb5Authenticate.conf @@ -0,0 +1,12 @@ +####################################################### +# # +# CASA Authentication Token System configuration file # +# for module: # +# # +# Krb5Authenticate # +# # +####################################################### + +LibraryName \Program Files\novell\casa\lib\krb5mech.dll + + diff --git a/auth_token/client/mechanisms/krb5/interface.c b/auth_token/client/mechanisms/krb5/interface.c new file mode 100644 index 00000000..2fbdf3f4 --- /dev/null +++ b/auth_token/client/mechanisms/krb5/interface.c @@ -0,0 +1,207 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// Authentication Token Interface instance data +// +typedef struct _AuthTokenIfInstance +{ + int refCount; + AuthTokenIf authTokenIf; + +} AuthTokenIfInstance, *PAuthTokenIfInstance; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// AuthTokenIf variables +static +int g_numAuthTokenIfObjs = 0; + + +//++======================================================================= +static +int SSCS_CALL +AuthTokenIf_AddReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +// +// L2 +//=======================================================================-- +{ + int refCount; + AuthTokenIfInstance *pAuthTokenIfInstance = CONTAINING_RECORD(pIfInstance, AuthTokenIfInstance, authTokenIf); + + DbgTrace(2, "-AuthTokenIf_AddReference- Start\n", 0); + + // Increment the reference count on the object + pAuthTokenIfInstance->refCount ++; + refCount = pAuthTokenIfInstance->refCount; + + DbgTrace(2, "-AuthTokenIf_AddReference- End, refCount = %08X\n", refCount); + + return refCount; +} + + +//++======================================================================= +static +void SSCS_CALL +AuthTokenIf_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; + AuthTokenIfInstance *pAuthTokenIfInstance = CONTAINING_RECORD(pIfInstance, AuthTokenIfInstance, authTokenIf); + + DbgTrace(2, "-AuthTokenIf_ReleaseReference- Start\n", 0); + + // Decrement the reference count on the object and determine if it needs to + // be released. + pAuthTokenIfInstance->refCount --; + if (pAuthTokenIfInstance->refCount == 0) + { + // The object needs to be released, forget about it. + freeObj = true; + g_numAuthTokenIfObjs --; + } + + // Free object if necessary + if (freeObj) + free(pAuthTokenIfInstance); + + DbgTrace(2, "-AuthTokenIf_ReleaseReference- End\n", 0); +} + + +//++======================================================================= +CasaStatus SSCS_CALL +GET_AUTH_TOKEN_INTERFACE_RTN( + IN const ConfigIf *pModuleConfigIf, + INOUT AuthTokenIf **ppAuthTokenIf) +// +// Arguments: +// pModuleConfigIf - +// Pointer to configuration interface instance for the module. +// +// ppAuthTokenIf - +// Pointer to variable that will receive pointer to AuthTokenIf +// instance. +// +// Returns: +// Casa Status +// +// Description: +// Gets authentication token interface instance. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + AuthTokenIfInstance *pAuthTokenIfInstance; + + + DbgTrace(1, "-GetAuthTokenInterface- Start\n", 0); + + // Validate input parameters + if (pModuleConfigIf == NULL + || ppAuthTokenIf == NULL) + { + DbgTrace(0, "-GetAuthTokenInterface- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Allocate space for the interface instance + pAuthTokenIfInstance = malloc(sizeof(*pAuthTokenIfInstance)); + if (pAuthTokenIfInstance) + { + // Initialize the interface instance data + pAuthTokenIfInstance->refCount = 1; + pAuthTokenIfInstance->authTokenIf.addReference = AuthTokenIf_AddReference; + pAuthTokenIfInstance->authTokenIf.releaseReference = AuthTokenIf_ReleaseReference; + pAuthTokenIfInstance->authTokenIf.getAuthToken = AuthTokenIf_GetAuthToken; + + // Keep track of this object + g_numAuthTokenIfObjs ++; + + // Return the interface to the caller + *ppAuthTokenIf = &pAuthTokenIfInstance->authTokenIf; + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-GetAuthTokenInterface- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + +exit: + + DbgTrace(1, "-GetAuthTokenInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/auth_token/client/mechanisms/krb5/internal.h b/auth_token/client/mechanisms/krb5/internal.h new file mode 100644 index 00000000..c4eb41d0 --- /dev/null +++ b/auth_token/client/mechanisms/krb5/internal.h @@ -0,0 +1,105 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +//===[ Include files ]===================================================== + +#include "platform.h" +#include +#include +#include "mech_if.h" + +//===[ Type definitions ]================================================== + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) +#endif + +// +// DbgTrace macro define +// +#define DbgTrace(LEVEL, X, Y) { \ + if (LEVEL == 0) \ + printf(X, Y); \ + else if (DebugLevel >= LEVEL) \ + printf(X, Y); \ +} + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Global externals ]================================================== + +extern int DebugLevel; + +//===[ External prototypes ]=============================================== + +// +// Defined in get.c +// + +extern +CasaStatus SSCS_CALL +AuthTokenIf_GetAuthToken( + IN const void *pIfInstance, + IN const char *pContext, + IN const char *pMechInfo, + INOUT char *pTokenBuf, + INOUT int *pTokenBufLen); + +extern +int +InitializeLibrary(void); + +// +// Defined in utils.c +// + +extern +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen); + +extern +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen); + + +//========================================================================= + +#endif // _INTERNAL_H_ diff --git a/auth_token/client/mechanisms/krb5/krb5.vcproj b/auth_token/client/mechanisms/krb5/krb5.vcproj new file mode 100644 index 00000000..4d0e49f2 --- /dev/null +++ b/auth_token/client/mechanisms/krb5/krb5.vcproj @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/auth_token/client/mechanisms/krb5/util.c b/auth_token/client/mechanisms/krb5/util.c new file mode 100644 index 00000000..634203f8 --- /dev/null +++ b/auth_token/client/mechanisms/krb5/util.c @@ -0,0 +1,282 @@ +/*********************************************************************** + * + * 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 ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Debug Level +int DebugLevel = 2; + +// Tables for Base64 encoding and decoding +static const int8_t g_Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const uint8_t g_Expand64[256] = +{ + /* ASCII table */ + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, + 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, + 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 +}; + + +//++======================================================================= +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int encodedSize; + + char *pTmp; + + DbgTrace(3, "-EncodeData- Start\n", 0); + + // Determine the encoded size and allocate a buffer to hold the encoded data + encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4; + pTmp = (char*) malloc(encodedSize); + *ppEncodedData = pTmp; + if (*ppEncodedData) + { + uint8_t *pOut, *pIn; + int i; + + // Setup pointers to move through the buffers + pIn = (uint8_t*) pData; + pOut = (uint8_t*) *ppEncodedData; + + // Perform the encoding + for (i = 0; i < dataLen - 2; i += 3) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2) | + ((int32_t)(pIn[i + 2] & 0xC0) >> 6)]; + *pOut++ = g_Base64[pIn[i + 2] & 0x3F]; + } + if (i < dataLen) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + if (i == (dataLen - 1)) + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4)]; + *pOut++ = '='; + } + else + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2)]; + } + *pOut++ = '='; + } + *pOut++ = '\0'; + + // Return the encoded data length + *pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-EncodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-EncodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int i, j; + int decodedSize; + + DbgTrace(3, "-DecodeData- Start\n", 0); + + // Determine the decoded size + for (i = 0, j = 0; i < encodedDataLen; i++) + if (g_Expand64[((uint8_t*) pEncodedData)[i]] < 64) + j++; + decodedSize = (j * 3 + 3) / 4; + + // Allocate buffer to hold the decoded data + *ppData = malloc(decodedSize); + if (*ppData) + { + bool endReached = false; + uint8_t c0, c1, c2, c3; + uint8_t *p, *q; + + // Initialize parameters that will be used during the decode operation + c0 = c1 = c2 = c3 = 0; + p = (uint8_t*) pEncodedData; + q = (uint8_t*) *ppData; + + // Decode the data + // + // Loop through the data, piecing back information. Any newlines, and/or + // carriage returns need to be skipped. + while (j > 4) + { + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + endReached = true; + break; + } + c0 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2); + j--; + endReached = true; + break; + } + c1 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4); + j -= 2; + endReached = true; + break; + } + c2 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6); + j -= 3; + endReached = true; + break; + } + c3 = *(p++); + + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6 | g_Expand64[c3]); + j -= 4; + } + if (!endReached) + { + if (j > 1) + *(q++) = (uint8_t)(g_Expand64[*p] << 2 | g_Expand64[p[1]] >> 4); + if (j > 2) + *(q++) = (uint8_t)(g_Expand64[p[1]] << 4 | g_Expand64[p[2]] >> 2); + if (j > 3) + *(q++) = (uint8_t)(g_Expand64[p[2]] << 6 | g_Expand64[p[3]]); + } + + // Return the length of the decoded data + *pDataLen = (int32_t)(q - (uint8_t*)*ppData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-DecodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-DecodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/auth_token/client/mechanisms/krb5/win32/dllsup.c b/auth_token/client/mechanisms/krb5/win32/dllsup.c new file mode 100644 index 00000000..8eecacef --- /dev/null +++ b/auth_token/client/mechanisms/krb5/win32/dllsup.c @@ -0,0 +1,132 @@ +/*********************************************************************** + * + * 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" + +//===[ External data ]===================================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +UINT32 g_ulCount = 0; +UINT32 g_ulLock = 0; +HANDLE g_hModule; + + +//++======================================================================= +BOOL APIENTRY DllMain( + HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +//=======================================================================-- +{ + BOOL retStatus = TRUE; + + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + { + g_hModule = hModule; + + // Initialize the library + if (InitializeLibrary() != 0) + { + // Failed to initialize the library + OutputDebugString("CASA_PW_MECH -DllMain- Library initialization failed\n"); + retStatus = FALSE; + } + break; + } + + case DLL_THREAD_ATTACH: + { + g_hModule = hModule; + break; + } + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + { + /* Don't uninitialize on windows + tbd + */ + break; + } + } + + return retStatus; +} + +//++======================================================================= +// +// DllCanUnloadNow +// +// Synopsis +// +// +STDAPI +DllCanUnloadNow() +// +// Input Arguments +// +// Ouput Arguments +// +// Return Value +// S_OK The DLL can be unloaded. +// S_FALSE The DLL cannot be unloaded now. +// +// Description +// An Exported Function. +// DLLs that support the OLE Component Object Model (COM) should implement +// and export DllCanUnloadNow. +// A call to DllCanUnloadNow determines whether the DLL from which it is +// exported is still in use. A DLL is no longer in use when it is not +// managing any existing objects (the reference count on all of its objects +// is 0). +// DllCanUnloadNow returns S_FALSE if there are any existing references to +// objects that the DLL manages. +// +// Environment +// +// See Also +// +//=======================================================================-- +{ + // tbd + return ((g_ulCount == 0 && g_ulLock == 0) ? S_OK : S_FALSE); +} + +//========================================================================= +//========================================================================= + diff --git a/auth_token/client/mechanisms/krb5/win32/get.c b/auth_token/client/mechanisms/krb5/win32/get.c new file mode 100644 index 00000000..fa1cdb7d --- /dev/null +++ b/auth_token/client/mechanisms/krb5/win32/get.c @@ -0,0 +1,266 @@ +/*********************************************************************** + * + * 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 ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +//++======================================================================= +CasaStatus SSCS_CALL +AuthTokenIf_GetAuthToken( + IN const void *pIfInstance, + IN const char *pContext, + IN const char *pMechInfo, + INOUT char *pTokenBuf, + INOUT int *pTokenBufLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pServiceConfigIf - +// Pointer to service config object to which the client is trying to +// authenticate. +// +// pContext - +// Pointer to null terminated string containing mechanism specific +// context information. Another name for context is Authentication +// Realm. +// +// pMechInfo - +// Pointer to null terminated string containing mechanism specific +// information. This is information is provided by the server to +// aid the mechanism to generate an authentication token. For +// example, the mechanism information for a Kerberos mechanism +// may be the service principal name to which the user will be +// authenticating. +// +// pTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pUserNameBuf is +// not large enough. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified service. +// +// L0 +//=======================================================================-- +{ + CasaStatus retStatus; + char *pKrbServiceName = pMechInfo; + + SECURITY_STATUS secStatus; + TimeStamp expiry; + CredHandle hCredentials = {0}; + + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Start\n", 0); + + // Validate input parameters + if (pIfInstance == NULL + || pContext == NULL + || pMechInfo == NULL + || pTokenBufLen == NULL + || (pTokenBuf == NULL && *pTokenBufLen != 0)) + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Acquire a credential handle for the current user + secStatus = AcquireCredentialsHandle(NULL, // no principal name + "Kerberos", // package name + SECPKG_CRED_OUTBOUND, + NULL, // no logon id + NULL, // no auth data + NULL, // no get key fn + NULL, // noget key arg + &hCredentials, + &expiry); + if (secStatus == SEC_E_OK) + { + CtxtHandle hContext = {0}; + SecBuffer sendTok; + SecBufferDesc outputDesc; + ULONG retFlags; + + // We acquired the credential, now initialize a security context + // so that we can authenticate the user to the specified service. + // + // First ready an output descriptor so that we can receive the + // token buffer. + outputDesc.cBuffers = 1; + outputDesc.pBuffers = &sendTok; + outputDesc.ulVersion = SECBUFFER_VERSION; + + sendTok.BufferType = SECBUFFER_TOKEN; + sendTok.cbBuffer = 0; + sendTok.pvBuffer = NULL; + + // Initialize the security context for the specified service + secStatus = InitializeSecurityContext(&hCredentials, + NULL, + pKrbServiceName, + ISC_REQ_ALLOCATE_MEMORY, + 0, // reserved + SECURITY_NATIVE_DREP, + NULL, + 0, // reserved + &hContext, + &outputDesc, + &retFlags, + &expiry); + if (secStatus == SEC_E_OK) + { + char *pEncodedToken; + int encodedTokenLen; + + // The security context was initialized, now return it to the caller after base64 encoding it. + // The token has been assembled, now encode it. + retStatus = EncodeData(sendTok.pvBuffer, + (const int) sendTok.cbBuffer, + &pEncodedToken, + &encodedTokenLen); + if (CASA_SUCCESS(retStatus)) + { + // Verify that the caller provided a buffer that is big enough + if (encodedTokenLen > *pTokenBufLen) + { + // The buffer is not big enough + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Insufficient buffer space provided\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + else + { + // The buffer provided is large enough, copy the data. + memcpy((void*) pTokenBuf, pEncodedToken, encodedTokenLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + + // Return the actual size or the size required + *pTokenBufLen = encodedTokenLen; + + // Free the buffer containing the encoded token + free(pEncodedToken); + } + + // Delete the security context + DeleteSecurityContext(&hContext); + } + else + { + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Failed to obtain the credentials handle, error = %08X\n", secStatus); + + // tdb - Set retStatus based on secStatus + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Free any buffer associated with the sendToken + if (sendTok.pvBuffer) + FreeContextBuffer(sendTok.pvBuffer); + + // Free the credential handle obtained + FreeCredentialsHandle(&hCredentials); + + } + else + { + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Failed to obtain the credentials handle, error = %08X\n", secStatus); + + // tdb - Set retStatus based on secStatus + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_KRB5TOKEN, + CASA_STATUS_NO_CREDENTIALS); + } + +exit: + + DbgTrace(1, "-AuthTokenIf_GetAuthToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +int +InitializeLibrary(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + int retStatus = 0; + + DbgTrace(1, "-InitializeLibrary- Start\n", 0); + + + DbgTrace(1, "-InitializeLibrary- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/auth_token/client/mechanisms/krb5/win32/krb5mech.def b/auth_token/client/mechanisms/krb5/win32/krb5mech.def new file mode 100644 index 00000000..1605afcf --- /dev/null +++ b/auth_token/client/mechanisms/krb5/win32/krb5mech.def @@ -0,0 +1,10 @@ +LIBRARY KRB5MECH +DESCRIPTION 'CASA Kerberos V Authentication Mechanism Library.' + + +EXPORTS +; DllRegisterServer PRIVATE +; DllUnregisterServer PRIVATE +; DllGetClassObject PRIVATE + GetAuthTokenInterface PRIVATE +; DllCanUnloadNow PRIVATE \ No newline at end of file diff --git a/auth_token/client/mechanisms/krb5/win32/platform.h b/auth_token/client/mechanisms/krb5/win32/platform.h new file mode 100644 index 00000000..e6ea6f1d --- /dev/null +++ b/auth_token/client/mechanisms/krb5/win32/platform.h @@ -0,0 +1,77 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ + +//===[ Include files ]===================================================== + +#include +#include +#include +#include +#include + +//===[ Type definitions ]================================================== + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) +#endif + +// +// DbgTrace macro define +// +#define DbgTrace(LEVEL, X, Y) { \ +char printBuff[256]; \ + if (LEVEL == 0) \ + { \ + _snprintf(printBuff, sizeof(printBuff), X, Y); \ + printf("Krb5Mech %s", printBuff); \ + } \ + else if (DebugLevel >= LEVEL) \ + { \ + _snprintf(printBuff, sizeof(printBuff), X, Y); \ + printf("Krb5Mech %s", printBuff); \ + } \ +} + +#define bool BOOLEAN +#define true TRUE +#define false FALSE + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + + +//========================================================================= + +#endif // _PLATFORM_H_ + diff --git a/auth_token/client/mechanisms/krb5/win32/platutils.c b/auth_token/client/mechanisms/krb5/win32/platutils.c new file mode 100644 index 00000000..869b581c --- /dev/null +++ b/auth_token/client/mechanisms/krb5/win32/platutils.c @@ -0,0 +1,35 @@ +/*********************************************************************** + * + * 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 ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + diff --git a/auth_token/client/mechanisms/pwd/PwdAuthenticate.conf b/auth_token/client/mechanisms/pwd/PwdAuthenticate.conf new file mode 100644 index 00000000..171f06e0 --- /dev/null +++ b/auth_token/client/mechanisms/pwd/PwdAuthenticate.conf @@ -0,0 +1,12 @@ +####################################################### +# # +# CASA Authentication Token System configuration file # +# for module: # +# # +# PwdAuthenticate # +# # +####################################################### + +LibraryName \Program Files\novell\casa\lib\pwmech.dll + + diff --git a/auth_token/client/mechanisms/pwd/get.c b/auth_token/client/mechanisms/pwd/get.c new file mode 100644 index 00000000..47d1807c --- /dev/null +++ b/auth_token/client/mechanisms/pwd/get.c @@ -0,0 +1,359 @@ +/*********************************************************************** + * + * 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 ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +//++======================================================================= +static +CasaStatus +GetUserCredentials( + IN const char *pRealm, + INOUT char **ppUsername, + INOUT char **ppPassword) +// +// Arguments: +// pRealm - +// The realm to which the credentials apply. +// +// ppUsername - +// Pointer to variable that will receive buffer with the username. +// +// ppPassword - +// Pointer to variable that will receive buffer with the password. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication credentials for the specified realm. +// +// L0 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_UNSUCCESSFUL); + char *pUsername; + char *pPassword; + int rcode = NSSCS_E_OBJECT_NOT_FOUND; + int32_t credtype = SSCS_CRED_TYPE_BASIC_F; + SSCS_BASIC_CREDENTIAL credential = {0}; + SSCS_SECRET_ID_T secretId = {0}; + SSCS_SECRET_ID_T sharedSecretId = {0}; + + DbgTrace(1, "-GetUserCredentials- Start\n", 0); + + // Initialize output parameters + *ppUsername = NULL; + *ppPassword = NULL; + + // Get the length of the realm string into the secret id structure + // and verify thatr it is not too long. + secretId.len = sscs_Utf8Strlen(pRealm) + 1; + if (secretId.len <= NSSCS_MAX_SECRET_ID_LEN) + { + // Set the secret id in the structure + sscs_Utf8Strcpy(secretId.id, pRealm); + + // Specify that we want the common name + credential.unFlags = USERNAME_TYPE_CN_F; + + // Now try to get the credentials + rcode = miCASAGetCredential(0, + &secretId, + NULL, + &credtype, //SSCS_CRED_TYPE_BASIC_F, + &credential, + NULL); + if (rcode != NSSCS_SUCCESS) + { + // There were no credentials for the realm, now try to obtain the + // desktop credentials. + secretId.len = sscs_Utf8Strlen("Desktop") + 1; + sscs_Utf8Strcpy(secretId.id, "Desktop"); + rcode = miCASAGetCredential(0, + &secretId, + NULL, + &credtype, //SSCS_CRED_TYPE_BASIC_F, + &credential, + NULL); + } + } + else + { + DbgTrace(0, "-GetUserCredentials- Realm name too long\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Proceed based on the result of the operatiosn above + if (rcode == NSSCS_SUCCESS + && credential.username != NULL + && credential.password != NULL) + { + // Allocate a buffer to return the username + pUsername = (char*) malloc(strlen(credential.username) + 1); + if (pUsername) + { + // Copy the username into the buffer that we will be returning + strcpy(pUsername, credential.username); + + // Allocate a buffer to return the password + pPassword = (char*) malloc(strlen(credential.password) + 1); + if (pPassword) + { + // Copy the password into the buffer that we will be returning + strcpy(pPassword, credential.password); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-GetUserCredentials- Buffer allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + + // Free the buffer allocated for the username + free(pUsername); + } + } + else + { + DbgTrace(0, "-GetUserCredentials- Buffer allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + + // Return the buffers to the caller if successful + if (CASA_SUCCESS(retStatus)) + { + *ppUsername = pUsername; + *ppPassword = pPassword; + } + + DbgTrace(1, "-GetUserCredentials- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus SSCS_CALL +AuthTokenIf_GetAuthToken( + IN const void *pIfInstance, + IN const char *pContext, + IN const char *pMechInfo, + INOUT char *pTokenBuf, + INOUT int *pTokenBufLen) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// pServiceConfigIf - +// Pointer to service config object to which the client is trying to +// authenticate. +// +// pContext - +// Pointer to null terminated string containing mechanism specific +// context information. Another name for context is Authentication +// Realm. +// +// pMechInfo - +// Pointer to null terminated string containing mechanism specific +// information. This is information is provided by the server to +// aid the mechanism to generate an authentication token. For +// example, the mechanism information for a Kerberos mechanism +// may be the service principal name to which the user will be +// authenticating. +// +// pTokenBuf - +// Pointer to buffer that will receive the authentication +// token. The length of this buffer is specified by the +// pTokenBufLen parameter. Note that the the authentication +// token will be in the form of a NULL terminated string. +// +// pTokenBufLen - +// Pointer to integer that contains the length of the +// buffer pointed at by pTokenBuf. Upon return of the +// function, the integer will contain the actual length +// of the authentication token if the function successfully +// completes or the buffer length required if the function +// fails because the buffer pointed at by pUserNameBuf is +// not large enough. +// +// Returns: +// Casa Status +// +// Description: +// Get authentication token to authenticate user to specified service. +// +// L0 +//=======================================================================-- +{ + CasaStatus retStatus; + char *pUsername = NULL; + char *pPassword = NULL; + char *pToken; + + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Start\n", 0); + + // Validate input parameters + if (pIfInstance == NULL + || pContext == NULL + || pMechInfo == NULL + || pTokenBufLen == NULL + || (pTokenBuf == NULL && *pTokenBufLen != 0)) + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Get the user credentials + retStatus = GetUserCredentials(pContext, &pUsername, &pPassword); + if (CASA_SUCCESS(retStatus)) + { + // Now construct the PW token with the following format: + // "username\r\n" + "password\r\n" + // + // First allocate a buffer large enough to hold the token + pToken = (char*) malloc(strlen(pUsername) + 2 + strlen(pPassword) + 2 + 1); + if (pToken) + { + char *pEncodedToken; + int encodedTokenLen; + + // Now assemble the token + sprintf(pToken, "%s\r\n%s\r\n", pUsername, pPassword); + + // The token has been assembled, now encode it. + retStatus = EncodeData(pToken, + (const int) strlen(pToken), + &pEncodedToken, + &encodedTokenLen); + if (CASA_SUCCESS(retStatus)) + { + // Verify that the caller provided a buffer that is big enough + if (encodedTokenLen > *pTokenBufLen) + { + // The buffer is not big enough + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Insufficient buffer space provided\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_BUFFER_OVERFLOW); + } + else + { + // The buffer provided is large enough, copy the data. + memcpy((void*) pTokenBuf, pEncodedToken, encodedTokenLen); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + + // Return the actual size or the size required + *pTokenBufLen = encodedTokenLen; + + // Free the buffer containing the encoded token + free(pEncodedToken); + } + + // Free the buffer allocated for the token + free(pToken); + } + else + { + DbgTrace(0, "-AuthTokenIf_GetAuthToken- Buffer allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + // Free allocated buffers + free(pUsername); + free(pPassword); + } + else + { + DbgTrace(1, "-AuthTokenIf_GetAuthToken- Failed to obtain the user credentials\n", 0); + } + +exit: + + DbgTrace(1, "-AuthTokenIf_GetAuthToken- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +int +InitializeLibrary(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + int retStatus = 0; + + DbgTrace(1, "-InitializeLibrary- Start\n", 0); + + + DbgTrace(1, "-InitializeLibrary- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/auth_token/client/mechanisms/pwd/interface.c b/auth_token/client/mechanisms/pwd/interface.c new file mode 100644 index 00000000..2fbdf3f4 --- /dev/null +++ b/auth_token/client/mechanisms/pwd/interface.c @@ -0,0 +1,207 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// Authentication Token Interface instance data +// +typedef struct _AuthTokenIfInstance +{ + int refCount; + AuthTokenIf authTokenIf; + +} AuthTokenIfInstance, *PAuthTokenIfInstance; + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// AuthTokenIf variables +static +int g_numAuthTokenIfObjs = 0; + + +//++======================================================================= +static +int SSCS_CALL +AuthTokenIf_AddReference( + IN const void *pIfInstance) +// +// Arguments: +// pIfInstance - +// Pointer to interface object. +// +// Returns: +// Interface reference count. +// +// Description: +// Increases interface reference count. +// +// L2 +//=======================================================================-- +{ + int refCount; + AuthTokenIfInstance *pAuthTokenIfInstance = CONTAINING_RECORD(pIfInstance, AuthTokenIfInstance, authTokenIf); + + DbgTrace(2, "-AuthTokenIf_AddReference- Start\n", 0); + + // Increment the reference count on the object + pAuthTokenIfInstance->refCount ++; + refCount = pAuthTokenIfInstance->refCount; + + DbgTrace(2, "-AuthTokenIf_AddReference- End, refCount = %08X\n", refCount); + + return refCount; +} + + +//++======================================================================= +static +void SSCS_CALL +AuthTokenIf_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; + AuthTokenIfInstance *pAuthTokenIfInstance = CONTAINING_RECORD(pIfInstance, AuthTokenIfInstance, authTokenIf); + + DbgTrace(2, "-AuthTokenIf_ReleaseReference- Start\n", 0); + + // Decrement the reference count on the object and determine if it needs to + // be released. + pAuthTokenIfInstance->refCount --; + if (pAuthTokenIfInstance->refCount == 0) + { + // The object needs to be released, forget about it. + freeObj = true; + g_numAuthTokenIfObjs --; + } + + // Free object if necessary + if (freeObj) + free(pAuthTokenIfInstance); + + DbgTrace(2, "-AuthTokenIf_ReleaseReference- End\n", 0); +} + + +//++======================================================================= +CasaStatus SSCS_CALL +GET_AUTH_TOKEN_INTERFACE_RTN( + IN const ConfigIf *pModuleConfigIf, + INOUT AuthTokenIf **ppAuthTokenIf) +// +// Arguments: +// pModuleConfigIf - +// Pointer to configuration interface instance for the module. +// +// ppAuthTokenIf - +// Pointer to variable that will receive pointer to AuthTokenIf +// instance. +// +// Returns: +// Casa Status +// +// Description: +// Gets authentication token interface instance. +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + AuthTokenIfInstance *pAuthTokenIfInstance; + + + DbgTrace(1, "-GetAuthTokenInterface- Start\n", 0); + + // Validate input parameters + if (pModuleConfigIf == NULL + || ppAuthTokenIf == NULL) + { + DbgTrace(0, "-GetAuthTokenInterface- Invalid input parameter\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INVALID_PARAMETER); + goto exit; + } + + // Allocate space for the interface instance + pAuthTokenIfInstance = malloc(sizeof(*pAuthTokenIfInstance)); + if (pAuthTokenIfInstance) + { + // Initialize the interface instance data + pAuthTokenIfInstance->refCount = 1; + pAuthTokenIfInstance->authTokenIf.addReference = AuthTokenIf_AddReference; + pAuthTokenIfInstance->authTokenIf.releaseReference = AuthTokenIf_ReleaseReference; + pAuthTokenIfInstance->authTokenIf.getAuthToken = AuthTokenIf_GetAuthToken; + + // Keep track of this object + g_numAuthTokenIfObjs ++; + + // Return the interface to the caller + *ppAuthTokenIf = &pAuthTokenIfInstance->authTokenIf; + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-GetAuthTokenInterface- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + +exit: + + DbgTrace(1, "-GetAuthTokenInterface- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/auth_token/client/mechanisms/pwd/internal.h b/auth_token/client/mechanisms/pwd/internal.h new file mode 100644 index 00000000..3e077cfe --- /dev/null +++ b/auth_token/client/mechanisms/pwd/internal.h @@ -0,0 +1,107 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _INTERNAL_H_ +#define _INTERNAL_H_ + +//===[ Include files ]===================================================== + +#include "platform.h" +#include +#include +#include +#include +#include "mech_if.h" + +//===[ Type definitions ]================================================== + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) +#endif + +// +// DbgTrace macro define +// +#define DbgTrace(LEVEL, X, Y) { \ + if (LEVEL == 0) \ + printf(X, Y); \ + else if (DebugLevel >= LEVEL) \ + printf(X, Y); \ +} + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +//===[ Global externals ]================================================== + +extern int DebugLevel; + +//===[ External prototypes ]=============================================== + +// +// Defined in get.c +// + +extern +CasaStatus SSCS_CALL +AuthTokenIf_GetAuthToken( + IN const void *pIfInstance, + IN const char *pContext, + IN const char *pMechInfo, + INOUT char *pTokenBuf, + INOUT int *pTokenBufLen); + +extern +int +InitializeLibrary(void); + +// +// Defined in utils.c +// + +extern +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen); + +extern +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen); + +//========================================================================= + +#endif // _INTERNAL_H_ + diff --git a/auth_token/client/mechanisms/pwd/pwd.vcproj b/auth_token/client/mechanisms/pwd/pwd.vcproj new file mode 100644 index 00000000..fd5bf95f --- /dev/null +++ b/auth_token/client/mechanisms/pwd/pwd.vcproj @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/auth_token/client/mechanisms/pwd/util.c b/auth_token/client/mechanisms/pwd/util.c new file mode 100644 index 00000000..634203f8 --- /dev/null +++ b/auth_token/client/mechanisms/pwd/util.c @@ -0,0 +1,282 @@ +/*********************************************************************** + * + * 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 ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Debug Level +int DebugLevel = 2; + +// Tables for Base64 encoding and decoding +static const int8_t g_Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const uint8_t g_Expand64[256] = +{ + /* ASCII table */ + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, + 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, + 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 +}; + + +//++======================================================================= +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int encodedSize; + + char *pTmp; + + DbgTrace(3, "-EncodeData- Start\n", 0); + + // Determine the encoded size and allocate a buffer to hold the encoded data + encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4; + pTmp = (char*) malloc(encodedSize); + *ppEncodedData = pTmp; + if (*ppEncodedData) + { + uint8_t *pOut, *pIn; + int i; + + // Setup pointers to move through the buffers + pIn = (uint8_t*) pData; + pOut = (uint8_t*) *ppEncodedData; + + // Perform the encoding + for (i = 0; i < dataLen - 2; i += 3) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2) | + ((int32_t)(pIn[i + 2] & 0xC0) >> 6)]; + *pOut++ = g_Base64[pIn[i + 2] & 0x3F]; + } + if (i < dataLen) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + if (i == (dataLen - 1)) + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4)]; + *pOut++ = '='; + } + else + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2)]; + } + *pOut++ = '='; + } + *pOut++ = '\0'; + + // Return the encoded data length + *pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-EncodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-EncodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int i, j; + int decodedSize; + + DbgTrace(3, "-DecodeData- Start\n", 0); + + // Determine the decoded size + for (i = 0, j = 0; i < encodedDataLen; i++) + if (g_Expand64[((uint8_t*) pEncodedData)[i]] < 64) + j++; + decodedSize = (j * 3 + 3) / 4; + + // Allocate buffer to hold the decoded data + *ppData = malloc(decodedSize); + if (*ppData) + { + bool endReached = false; + uint8_t c0, c1, c2, c3; + uint8_t *p, *q; + + // Initialize parameters that will be used during the decode operation + c0 = c1 = c2 = c3 = 0; + p = (uint8_t*) pEncodedData; + q = (uint8_t*) *ppData; + + // Decode the data + // + // Loop through the data, piecing back information. Any newlines, and/or + // carriage returns need to be skipped. + while (j > 4) + { + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + endReached = true; + break; + } + c0 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2); + j--; + endReached = true; + break; + } + c1 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4); + j -= 2; + endReached = true; + break; + } + c2 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6); + j -= 3; + endReached = true; + break; + } + c3 = *(p++); + + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6 | g_Expand64[c3]); + j -= 4; + } + if (!endReached) + { + if (j > 1) + *(q++) = (uint8_t)(g_Expand64[*p] << 2 | g_Expand64[p[1]] >> 4); + if (j > 2) + *(q++) = (uint8_t)(g_Expand64[p[1]] << 4 | g_Expand64[p[2]] >> 2); + if (j > 3) + *(q++) = (uint8_t)(g_Expand64[p[2]] << 6 | g_Expand64[p[3]]); + } + + // Return the length of the decoded data + *pDataLen = (int32_t)(q - (uint8_t*)*ppData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-DecodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_PWTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-DecodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/auth_token/client/mechanisms/pwd/win32/dllsup.c b/auth_token/client/mechanisms/pwd/win32/dllsup.c new file mode 100644 index 00000000..8eecacef --- /dev/null +++ b/auth_token/client/mechanisms/pwd/win32/dllsup.c @@ -0,0 +1,132 @@ +/*********************************************************************** + * + * 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" + +//===[ External data ]===================================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +UINT32 g_ulCount = 0; +UINT32 g_ulLock = 0; +HANDLE g_hModule; + + +//++======================================================================= +BOOL APIENTRY DllMain( + HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +//=======================================================================-- +{ + BOOL retStatus = TRUE; + + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + { + g_hModule = hModule; + + // Initialize the library + if (InitializeLibrary() != 0) + { + // Failed to initialize the library + OutputDebugString("CASA_PW_MECH -DllMain- Library initialization failed\n"); + retStatus = FALSE; + } + break; + } + + case DLL_THREAD_ATTACH: + { + g_hModule = hModule; + break; + } + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + { + /* Don't uninitialize on windows + tbd + */ + break; + } + } + + return retStatus; +} + +//++======================================================================= +// +// DllCanUnloadNow +// +// Synopsis +// +// +STDAPI +DllCanUnloadNow() +// +// Input Arguments +// +// Ouput Arguments +// +// Return Value +// S_OK The DLL can be unloaded. +// S_FALSE The DLL cannot be unloaded now. +// +// Description +// An Exported Function. +// DLLs that support the OLE Component Object Model (COM) should implement +// and export DllCanUnloadNow. +// A call to DllCanUnloadNow determines whether the DLL from which it is +// exported is still in use. A DLL is no longer in use when it is not +// managing any existing objects (the reference count on all of its objects +// is 0). +// DllCanUnloadNow returns S_FALSE if there are any existing references to +// objects that the DLL manages. +// +// Environment +// +// See Also +// +//=======================================================================-- +{ + // tbd + return ((g_ulCount == 0 && g_ulLock == 0) ? S_OK : S_FALSE); +} + +//========================================================================= +//========================================================================= + diff --git a/auth_token/client/mechanisms/pwd/win32/platform.h b/auth_token/client/mechanisms/pwd/win32/platform.h new file mode 100644 index 00000000..1f551693 --- /dev/null +++ b/auth_token/client/mechanisms/pwd/win32/platform.h @@ -0,0 +1,75 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _PLATFORM_H_ +#define _PLATFORM_H_ + +//===[ Include files ]===================================================== + +#include +#include +#include + +//===[ Type definitions ]================================================== + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) +#endif + +// +// DbgTrace macro define +// +#define DbgTrace(LEVEL, X, Y) { \ +char printBuff[256]; \ + if (LEVEL == 0) \ + { \ + _snprintf(printBuff, sizeof(printBuff), X, Y); \ + printf("PwdMech %s", printBuff); \ + } \ + else if (DebugLevel >= LEVEL) \ + { \ + _snprintf(printBuff, sizeof(printBuff), X, Y); \ + printf("PwdMech %s", printBuff); \ + } \ +} + +#define bool BOOLEAN +#define true TRUE +#define false FALSE + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + + +//========================================================================= + +#endif // _PLATFORM_H_ + diff --git a/auth_token/client/mechanisms/pwd/win32/platutils.c b/auth_token/client/mechanisms/pwd/win32/platutils.c new file mode 100644 index 00000000..869b581c --- /dev/null +++ b/auth_token/client/mechanisms/pwd/win32/platutils.c @@ -0,0 +1,35 @@ +/*********************************************************************** + * + * 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 ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + diff --git a/auth_token/client/mechanisms/pwd/win32/pwmech.def b/auth_token/client/mechanisms/pwd/win32/pwmech.def new file mode 100644 index 00000000..0557e401 --- /dev/null +++ b/auth_token/client/mechanisms/pwd/win32/pwmech.def @@ -0,0 +1,10 @@ +LIBRARY PWMECH +DESCRIPTION 'CASA PW Authentication Mechanism Library.' + + +EXPORTS +; DllRegisterServer PRIVATE +; DllUnregisterServer PRIVATE +; DllGetClassObject PRIVATE + GetAuthTokenInterface PRIVATE +; DllCanUnloadNow PRIVATE \ No newline at end of file diff --git a/auth_token/client/proto.h b/auth_token/client/proto.h new file mode 100644 index 00000000..7aebd81f --- /dev/null +++ b/auth_token/client/proto.h @@ -0,0 +1,66 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +#ifndef _PROTO_H_ +#define _PROTO_H_ + +//===[ Include files ]===================================================== + + +//===[ Type definitions ]================================================== + +// +// XML Constants for the documents exchanged between the CASA Client +// and the CASA Server. +// +#define XML_DECLARATION "" +#define AUTH_REQUEST_ELEMENT_NAME "auth_req" +#define AUTH_RESPONSE_ELEMENT_NAME "auth_resp" +#define GET_AUTH_POLICY_REQUEST_ELEMENT_NAME "get_auth_policy_req" +#define GET_AUTH_POLICY_RESPONSE_ELEMENT_NAME "get_auth_policy_resp" +#define GET_AUTH_TOKEN_REQUEST_ELEMENT_NAME "get_auth_tok_req" +#define GET_AUTH_TOKEN_RESPONSE_ELEMENT_NAME "get_auth_tok_resp" +#define AUTH_MECH_TOKEN_ELEMENT_NAME "auth_mech_token" +#define AUTH_TOKEN_ELEMENT_NAME "auth_token" +#define AUTH_POLICY_ELEMENT_NAME "auth_policy" +#define AUTH_SOURCE_ELEMENT_NAME "auth_source" +#define STATUS_ELEMENT_NAME "status" +#define SESSION_TOKEN_ELEMENT_NAME "session_token" +#define LIFETIME_ELEMENT_NAME "lifetime" +#define DESCRIPTION_ELEMENT_NAME "description" +#define SERVICE_ELEMENT_NAME "service" +#define HOST_ELEMENT_NAME "host" +#define REALM_ELEMENT_NAME "realm" +#define MECHANISM_ELEMENT_NAME "mechanism" +#define MECHANISM_INFO_ELEMENT_NAME "mechanism_info" + +// +// HTTP Status Codes +// +#define HTTP_OK_STATUS_CODE "200" +#define HTTP_UNAUTHORIZED_STATUS_CODE "401" +#define HTTP_SERVER_ERROR_STATUS_CODE "500" + + +#endif // _PROTO_H_ diff --git a/auth_token/client/test/CASA_Auth.cpp b/auth_token/client/test/CASA_Auth.cpp new file mode 100644 index 00000000..f8b7c363 --- /dev/null +++ b/auth_token/client/test/CASA_Auth.cpp @@ -0,0 +1,165 @@ +/*********************************************************************** + * + * 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 +#include "casa_auth_token.h" + +int main(int argc, char* argv[]) +{ + int retStatus; + char authToken[4096]; + int authTokenLen = sizeof(authToken); + + // Now lets obtain a token for our service + retStatus = ObtainAuthToken("testService@137.65.132.44", authToken, &authTokenLen); + if (retStatus) + printf("ObtainAuthToken failed with status %d\n", retStatus); + else + { + char serverAddr[] = "137.65.132.44"; + char *pServerAddress = serverAddr; + int serverPort = 4444; + SOCKET sock; + struct sockaddr_in localAddr = {0}; + struct sockaddr_in remoteAddr = {0}; + struct linger linger_opt = {1, 15}; + struct hostent *pLookupResult; + int winsockStartupResult; + WSADATA winsockData; + + //printf("ObtainAuthToken succedded, token = %s\n", authToken); + printf("ObtainAuthToken succedded, tokenlen = %d\n", authTokenLen); + + // Send the token to the server + // + // First initialize winsock + if ((winsockStartupResult = WSAStartup(MAKEWORD(2,2), &winsockData)) == 0) + { + // Open socket + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock != INVALID_SOCKET) + { + // Setup the local address structure + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + // Bind socket + if (!bind(sock, (const struct sockaddr*) &localAddr, sizeof(struct sockaddr_in))) + { + // Resolve the server address + pLookupResult = gethostbyname(pServerAddress); + if (pLookupResult) + { + // Validate the address type returned + if (pLookupResult->h_addrtype == AF_INET) + { + int numAddressesFound = 0; + + // Determine how many addresses where returned + while (pLookupResult->h_addr_list[numAddressesFound] != NULL) + { + //printf("ServerAddress = %08X\n", *((int*) pLookupResult->h_addr_list[numAddressesFound])); + numAddressesFound ++; + } + //printf("Found %d addresses\n", numAddressesFound); + + + // Setup the remote address structure with the lookup results + remoteAddr.sin_family = AF_INET; + remoteAddr.sin_port = htons(serverPort); + remoteAddr.sin_addr.s_addr = *((int*) pLookupResult->h_addr_list[0]); // Short-cut + //printf("ServerAddress = %08X\n", remoteAddr.sin_addr.s_addr); + + // Perform connect operation + if (connect(sock, + (struct sockaddr*) &remoteAddr, + sizeof(struct sockaddr_in)) == SOCKET_ERROR) + { + printf("main()- Connection creation failed, error = %d\n", WSAGetLastError()); + } + else + { + // Now the connection is setup, send the credentials to the server as one line. + // using our cheesy protocol followed by a hello string. + + // Send the username to the server (including NULL terminator) + //send(sock, userName, userNameBufLen, 0); + + // Send new line + //send(sock, "\n", 1, MSG_NOSIGNAL); + + // Send the token to the server (including NULL terminator) + send(sock, authToken, (int) strlen(authToken) + 1, 0); + + // Send new line + //send(sock, "\n", 1, 0); + + // Send "hello" + //send(sock, helloString, strlen(helloString) + 1, MSG_NOSIGNAL); + + // Send new line + //send(sock, "\n", 1, 0); + + // Shutdown the connection + shutdown(sock, 0); + } + } + else + { + printf("main()- Unsupported address type returned %08X\n", pLookupResult->h_addrtype); + } + } + else + { + printf("main()- Lookup for %s failed\n", pServerAddress); + } + } + else + { + printf("main()- Unable to bind socket, error = %d", errno); + } + + // Close the socket + setsockopt(sock, SOL_SOCKET, SO_LINGER, (const char*) &linger_opt, sizeof(linger_opt)); + closesocket(sock); + } + else + { + printf("main()- Unable to open socket, error = %d\n", errno); + } + + // Close winsock + WSACleanup(); + } + else + { + printf("main()- WSAStartup failed, error = %d\n", winsockStartupResult); + } + } + + printf("Enter to exit application\n"); + getchar(); + return 0; +} + diff --git a/auth_token/client/test/test.vcproj b/auth_token/client/test/test.vcproj new file mode 100644 index 00000000..642d2b56 --- /dev/null +++ b/auth_token/client/test/test.vcproj @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/auth_token/client/util.c b/auth_token/client/util.c new file mode 100644 index 00000000..4e887979 --- /dev/null +++ b/auth_token/client/util.c @@ -0,0 +1,321 @@ +/*********************************************************************** + * + * 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 ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Tables for Base64 encoding and decoding +static const int8_t g_Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const uint8_t g_Expand64[256] = +{ + /* ASCII table */ + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, + 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, + 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 +}; + + +//++======================================================================= +CasaStatus +EncodeData( + IN const void *pData, + IN const int32_t dataLen, + INOUT char **ppEncodedData, + INOUT int32_t *pEncodedDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int encodedSize; + + char *pTmp; + + DbgTrace(3, "-EncodeData- Start\n", 0); + + // Determine the encoded size and allocate a buffer to hold the encoded data + encodedSize = ((dataLen * 4 + 2) / 3) - (dataLen % 3 ) + 4; + pTmp = (char*) malloc(encodedSize); + *ppEncodedData = pTmp; + if (*ppEncodedData) + { + uint8_t *pOut, *pIn; + int i; + + // Setup pointers to move through the buffers + pIn = (uint8_t*) pData; + pOut = (uint8_t*) *ppEncodedData; + + // Perform the encoding + for (i = 0; i < dataLen - 2; i += 3) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2) | + ((int32_t)(pIn[i + 2] & 0xC0) >> 6)]; + *pOut++ = g_Base64[pIn[i + 2] & 0x3F]; + } + if (i < dataLen) + { + *pOut++ = g_Base64[(pIn[i] >> 2) & 0x3F]; + if (i == (dataLen - 1)) + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4)]; + *pOut++ = '='; + } + else + { + *pOut++ = g_Base64[((pIn[i] & 0x3) << 4) | + ((int32_t)(pIn[i + 1] & 0xF0) >> 4)]; + *pOut++ = g_Base64[((pIn[i + 1] & 0xF) << 2)]; + } + *pOut++ = '='; + } + *pOut++ = '\0'; + + // Return the encoded data length + *pEncodedDataLen = (int32_t)(pOut - (uint8_t*)*ppEncodedData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-EncodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-EncodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +CasaStatus +DecodeData( + IN const char *pEncodedData, + IN const int32_t encodedDataLen, // Does not include NULL terminator + INOUT void **ppData, + INOUT int32_t *pDataLen) +// +// Arguments: +// +// Returns: +// +// Description: +// +// L2 +//=======================================================================-- +{ + CasaStatus retStatus; + int i, j; + int decodedSize; + + DbgTrace(3, "-DecodeData- Start\n", 0); + + // Determine the decoded size + for (i = 0, j = 0; i < encodedDataLen; i++) + if (g_Expand64[((uint8_t*) pEncodedData)[i]] < 64) + j++; + decodedSize = (j * 3 + 3) / 4; + + // Allocate buffer to hold the decoded data + *ppData = malloc(decodedSize); + if (*ppData) + { + bool endReached = false; + uint8_t c0, c1, c2, c3; + uint8_t *p, *q; + + // Initialize parameters that will be used during the decode operation + c0 = c1 = c2 = c3 = 0; + p = (uint8_t*) pEncodedData; + q = (uint8_t*) *ppData; + + // Decode the data + // + // Loop through the data, piecing back information. Any newlines, and/or + // carriage returns need to be skipped. + while (j > 4) + { + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + endReached = true; + break; + } + c0 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2); + j--; + endReached = true; + break; + } + c1 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4); + j -= 2; + endReached = true; + break; + } + c2 = *(p++); + + while ((64 == g_Expand64[*p]) && (('\n' == *p) || ('\r' == *p))) + p++; + if (64 == g_Expand64[*p]) + { + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6); + j -= 3; + endReached = true; + break; + } + c3 = *(p++); + + *(q++) = (uint8_t)(g_Expand64[c0] << 2 | g_Expand64[c1] >> 4); + *(q++) = (uint8_t)(g_Expand64[c1] << 4 | g_Expand64[c2] >> 2); + *(q++) = (uint8_t)(g_Expand64[c2] << 6 | g_Expand64[c3]); + j -= 4; + } + if (!endReached) + { + if (j > 1) + *(q++) = (uint8_t)(g_Expand64[*p] << 2 | g_Expand64[p[1]] >> 4); + if (j > 2) + *(q++) = (uint8_t)(g_Expand64[p[1]] << 4 | g_Expand64[p[2]] >> 2); + if (j > 3) + *(q++) = (uint8_t)(g_Expand64[p[2]] << 6 | g_Expand64[p[3]]); + } + + // Return the length of the decoded data + *pDataLen = (int32_t)(q - (uint8_t*)*ppData); + + // Success + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-DecodeData- Buffer allocation failure\n", 0); + + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(3, "-DecodeData- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +int +dtoul( + IN char *cp, + IN int len) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + int n = 0; + int i; + + DbgTrace(2, "-dtoul- Start\n", 0); + + for (i = 0; i < len; i++, cp++) + { + // Verify that we are dealing with a valid digit + if (*cp >= '0' && *cp <= '9') + { + n = 10 * n + (*cp - '0'); + } + else + { + DbgTrace(0, "-dtoul- Found invalid digit\n", 0); + break; + } + } + + DbgTrace(2, "-dtoul- End, result = %d\n", n); + + return n; +} + + +//++======================================================================= +//++======================================================================= +//++======================================================================= + diff --git a/auth_token/client/win32/authtoken.def b/auth_token/client/win32/authtoken.def new file mode 100644 index 00000000..1862e07e --- /dev/null +++ b/auth_token/client/win32/authtoken.def @@ -0,0 +1,10 @@ +LIBRARY AUTHTOKEN +DESCRIPTION 'CASA Authentication Token Library.' + + +EXPORTS +; DllRegisterServer PRIVATE +; DllUnregisterServer PRIVATE +; DllGetClassObject PRIVATE + ObtainAuthToken PRIVATE +; DllCanUnloadNow PRIVATE \ No newline at end of file diff --git a/auth_token/client/win32/cache.c b/auth_token/client/win32/cache.c new file mode 100644 index 00000000..ea8e565d --- /dev/null +++ b/auth_token/client/win32/cache.c @@ -0,0 +1,875 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// Registry Key/Value defines used in the AuthCache +// +#define CASA_AUTH_CACHE_REG_KEY "CASA_Auth_Cache" +#define CREATION_TIME_REG_VALUE "CreationTime" +#define EXPIRATION_TIME_REG_VALUE "ExpirationTime" +#define STATUS_REG_VALUE "Status" +#define TOKEN_REG_VALUE "Token" + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// In memory auth cache list head +LIST_ENTRY authCacheListHead; + + +//++======================================================================= +AuthCacheEntry* +CreateAuthCacheEntry( + IN char *pCacheKeyName, + IN char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + AuthCacheEntry *pEntry; + + DbgTrace(1, "-CreateAuthCacheEntry- Start\n", 0); + + // Allocate space for the entry + pEntry = (AuthCacheEntry*) malloc(sizeof(*pEntry)); + if (pEntry) + { + // Zero the entry + memset(pEntry, 0, sizeof(*pEntry)); + + // Now allocate buffers to maintain copies of the CacheKeyName and host names + pEntry->pCacheKeyName = (char*) malloc(strlen(pCacheKeyName) + 1); + if (pEntry->pCacheKeyName) + { + pEntry->pHostName = (char*) malloc(strlen(pHostName) + 1); + if (pEntry->pHostName) + { + // Save the names within the entry + strcpy(pEntry->pCacheKeyName, pCacheKeyName); + strcpy(pEntry->pHostName, pHostName); + } + else + { + DbgTrace(0, "-CreateAuthCacheEntry- Unable to allocate buffer for host name\n", 0); + + // Free allocated resources + free(pEntry->pCacheKeyName); + free(pEntry); + + // Adjust return parameter + pEntry = NULL; + } + } + else + { + DbgTrace(0, "-CreateAuthCacheEntry- Unable to allocate buffer for the CacheKeyName\n", 0); + + // Free allocated resources + free(pEntry); + + // Adjust return parameter + pEntry = NULL; + } + } + else + { + DbgTrace(0, "-CreateAuthCacheEntry- Unable to allocate buffer for auth cache entry\n", 0); + } + + DbgTrace(1, "-CreateAuthCacheEntry- End, pEntry = %08X\n", pEntry); + + return pEntry; +} + + +//++======================================================================= +void +FreeAuthCacheEntry( + IN AuthCacheEntry *pEntry) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + DbgTrace(1, "-FreeAuthCacheEntry- Start\n", 0); + + // Free resources associated with the entry + if (pEntry->pToken) + free(pEntry->pToken); + + if (pEntry->pHostName) + free(pEntry->pHostName); + + if (pEntry->pCacheKeyName) + free(pEntry->pCacheKeyName); + + // Free the entry + free(pEntry); + + DbgTrace(1, "-FreeAuthCacheEntry- End\n", 0); +} + + +//++======================================================================= +static +BOOL +CacheEntryLifetimeExpired( + IN DWORD creationTime, + IN DWORD expirationTime) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + DWORD currentTime = GetTickCount(); + BOOL expired = FALSE; + + DbgTrace(2, "-CacheEntryLifetimeExpired- Start\n", 0); + + // Check if the clock has wrapped + if (currentTime >= creationTime) + { + // The clock has not wrapped, check if the + // expiration time has wrapped. + if (expirationTime > creationTime) + { + // The expiration time also has not wrapped, + // do a straight compare against the current + // time. + if (currentTime >= expirationTime) + { + // It has expired + expired = TRUE; + } + } + } + else + { + // The clock has wrapped, check if the expiration + // time also wrapped. + if (expirationTime > creationTime) + { + // The expiration time did not wrap, therefore + // it has been exceeded since the clock wrapped. + expired = TRUE; + } + else + { + // The expiration time also wrapped, do a straight + // compare against the current time. + if (currentTime >= expirationTime) + { + // It has expired + expired = TRUE; + } + } + } + + DbgTrace(2, "-CacheEntryLifetimeExpired- End, result = %08X\n", expired); + + return expired; +} + + +//++======================================================================= +AuthCacheEntry* +FindEntryInAuthCache( + IN char *pCacheKeyName, + IN char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + AuthCacheEntry *pEntry = NULL; + LIST_ENTRY *pListEntry; + + DbgTrace(1, "-FindEntryInAuthCache- Start\n", 0); + + // Examine the cache, if entry found then check if it has expired + // in which case we would want to remove it from the cache. + + // First look through the entries in our in-memory cache + pListEntry = authCacheListHead.Flink; + while (pListEntry != &authCacheListHead) + { + AuthCacheEntry *pWrkEntry; + + // get a pointer to the entry + pWrkEntry = CONTAINING_RECORD(pListEntry, AuthCacheEntry, listEntry); + + // Check if this is an entry for the appropriate host + if (strcmp(pHostName, pWrkEntry->pHostName) == 0) + { + // This is an entry for the appropriate host, now check if it is + // also for the appropriate CacheKeyName + if (strcmp(pCacheKeyName, pWrkEntry->pCacheKeyName) == 0) + { + // This entry is for the appropriate CacheKeyName, check if it + // has not expired. + if (CacheEntryLifetimeExpired(pWrkEntry->creationTime, pWrkEntry->expirationTime)) + { + // The lifetime of the entry has expired, remove it from the in-memory cache + // and free it. + RemoveEntryList(&pWrkEntry->listEntry); + FreeAuthCacheEntry(pWrkEntry); + } + else + { + // This cache entry is still good, use it. + pEntry = pWrkEntry; + } + + // No need to keep looking in the in-memory cache + break; + + } + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Look in the persistent cache if an entry was not found in the in-memory cache + if (pEntry == NULL) + { + LONG status; + HKEY hCASARegKey; + + // Open CASA Auth Cache Key + status = RegOpenKeyExA(HKEY_CURRENT_USER, + CASA_AUTH_CACHE_REG_KEY, + 0, + KEY_ALL_ACCESS, + &hCASARegKey); + if (status == ERROR_SUCCESS) + { + HKEY hHostRegKey; + + // CASA Auth Cache key opened, now try to open + // key for the host. + status = RegOpenKeyExA(hCASARegKey, + pHostName, + 0, + KEY_ALL_ACCESS, + &hHostRegKey); + if (status == ERROR_SUCCESS) + { + HKEY hCacheKeyNameRegKey; + + // Host key opened, now try to open key + // for the CacheKeyName. + status = RegOpenKeyExA(hHostRegKey, + pCacheKeyName, + 0, + KEY_ALL_ACCESS, + &hCacheKeyNameRegKey); + if (status == ERROR_SUCCESS) + { + DWORD creationTime; + DWORD expirationTime; + BOOL deleteCacheKeyNameKey = TRUE; + DWORD variableSz; + + // Key for the CacheKeyName key opened, now determine whether + // or not its lifetime has expired. + // + // Read the creation time value + variableSz = sizeof(creationTime); + status = RegQueryValueExA(hCacheKeyNameRegKey, + CREATION_TIME_REG_VALUE, + NULL, + NULL, + (LPBYTE) &creationTime, + &variableSz); + if (status == ERROR_SUCCESS) + { + // Read the expiration time + variableSz = sizeof(expirationTime); + status = RegQueryValueExA(hCacheKeyNameRegKey, + EXPIRATION_TIME_REG_VALUE, + NULL, + NULL, + (LPBYTE) &expirationTime, + &variableSz); + if (status == ERROR_SUCCESS) + { + // Check if the extry lifetime has been exceeded + if (CacheEntryLifetimeExpired(creationTime, expirationTime) == FALSE) + { + // Create a AuthCacheEntry + pEntry = CreateAuthCacheEntry(pCacheKeyName, pHostName); + if (pEntry) + { + BOOL entryInitialized = FALSE; + + // Start setting up the AuthCacheEntry + pEntry->creationTime = creationTime; + pEntry->expirationTime = expirationTime; + + // Read the status + variableSz = sizeof(pEntry->status); + status = RegQueryValueExA(hCacheKeyNameRegKey, + STATUS_REG_VALUE, + NULL, + NULL, + (LPBYTE) &pEntry->status, + &variableSz); + if (status == ERROR_SUCCESS) + { + // Check if there is also an auth token associated with + // this entry. + if (pEntry->status == CASA_STATUS_SUCCESS) + { + DWORD tokenSz = 0; + + // There should be an auth token associated with this CacheKeyName, + // first determine what size buffer to allocate for it. + status = RegQueryValueExA(hCacheKeyNameRegKey, + TOKEN_REG_VALUE, + NULL, + NULL, + (LPBYTE) pEntry->pToken, + &tokenSz); + if (status == ERROR_SUCCESS + || status == ERROR_MORE_DATA) + { + // Allocate buffer to hold the auth token + pEntry->pToken = (char*) malloc(tokenSz); + if (pEntry->pToken) + { + // Now read token into the allocated buffer + status = RegQueryValueExA(hCacheKeyNameRegKey, + TOKEN_REG_VALUE, + NULL, + NULL, + (LPBYTE) pEntry->pToken, + &tokenSz); + if (status == ERROR_SUCCESS) + { + // The cache entry has been properly initialized, + // add it to the in-memory cache. + entryInitialized = TRUE; + deleteCacheKeyNameKey = FALSE; + InsertHeadList(&authCacheListHead, &pEntry->listEntry); + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error reading token, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Unable to allocate buffer for token\n", 0); + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error reading token2, status = %d\n", status); + } + } + else + { + // There is no auth token associated with this entry + // + // The cache entry has been properly initialized, + // add it to the in-memory cache. + entryInitialized = TRUE; + deleteCacheKeyNameKey = FALSE; + InsertHeadList(&authCacheListHead, &pEntry->listEntry); + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error reading status, status = %d\n", status); + } + + // Free the auth cache entry if it was not successfully initialized + if (entryInitialized == FALSE) + { + FreeAuthCacheEntry(pEntry); + pEntry = NULL; + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error creating auth cache entry\n", 0); + } + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error reading expiration time, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error reading creation time, status = %d\n", status); + } + + // Close CacheKeyName key + RegCloseKey(hCacheKeyNameRegKey); + + // Delete the CacheKeyName key if necessary + if (deleteCacheKeyNameKey) + { + RegDeleteKey(hHostRegKey, pCacheKeyName); + } + } + + // Close host key + RegCloseKey(hHostRegKey); + } + + // Close CASA_Auth_Cache key + RegCloseKey(hCASARegKey); + } + else + { + DbgTrace(0, "-FindEntryInAuthCache- Error opening CASA Auth Cache key, status = %d\n", status); + } + } + + DbgTrace(1, "-FindEntryInAuthCache- End, pEntry = %08X\n", pEntry); + + return pEntry; +} + + +//++======================================================================= +void +AddEntryToAuthCache( + IN AuthCacheEntry *pEntry, + IN int entryLifetime) // seconds +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + LONG status; + HKEY hCASARegKey; + + DbgTrace(1, "-AddEntryToAuthCache- Start\n", 0); + + // Set the time when the entry was added to the cache + pEntry->creationTime = GetTickCount(); + + // First determine the time when the entry is due to expire + pEntry->expirationTime = pEntry->creationTime + (entryLifetime * 1000); + + // Save the entry in our persistent cache (registry) + // + // Open CASA Auth Cache key + status = RegOpenKeyExA(HKEY_CURRENT_USER, + CASA_AUTH_CACHE_REG_KEY, + 0, + KEY_ALL_ACCESS, + &hCASARegKey); + if (status == ERROR_SUCCESS) + { + HKEY hHostRegKey; + + // CASA_Auth_Cache key created or opened, now open or create key for the host. + status = RegCreateKeyExA(hCASARegKey, + pEntry->pHostName, + 0, + NULL, + REG_OPTION_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hHostRegKey, + NULL); + if (status == ERROR_SUCCESS) + { + HKEY hCacheKeyNameRegKey; + + // Host key created or opened, now create key for the CacheKeyName. + status = RegCreateKeyExA(hHostRegKey, + pEntry->pCacheKeyName, + 0, + NULL, + REG_OPTION_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &hCacheKeyNameRegKey, + NULL); + if (status == ERROR_SUCCESS) + { + // Write entry values + status = RegSetValueExA(hCacheKeyNameRegKey, + CREATION_TIME_REG_VALUE, + 0, + REG_DWORD, + (LPBYTE) &pEntry->creationTime, + sizeof(pEntry->creationTime)); + if (status == ERROR_SUCCESS) + { + status = RegSetValueExA(hCacheKeyNameRegKey, + EXPIRATION_TIME_REG_VALUE, + 0, + REG_DWORD, + (LPBYTE) &pEntry->expirationTime, + sizeof(pEntry->expirationTime)); + if (status == ERROR_SUCCESS) + { + status = RegSetValueExA(hCacheKeyNameRegKey, + STATUS_REG_VALUE, + 0, + REG_DWORD, + (LPBYTE) &pEntry->status, + sizeof(pEntry->status)); + if (status == ERROR_SUCCESS) + { + // Check if there is also an auth token associated with this entry + // this entry. + if (pEntry->status == CASA_STATUS_SUCCESS) + { + status = RegSetValueExA(hCacheKeyNameRegKey, + TOKEN_REG_VALUE, + 0, + REG_SZ, + (LPBYTE) pEntry->pToken, + (DWORD) strlen(pEntry->pToken) + 1); + if (status != ERROR_SUCCESS) + { + DbgTrace(0, "-AddEntryToAuthCache- Error setting token, status = %d\n", status); + } + } + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error setting status, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error setting expiration time, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error setting creation time, status = %d\n", status); + } + + // Close CacheKeyName key + RegCloseKey(hCacheKeyNameRegKey); + + // Delete the CacheKeyName key if not successful + if (status != ERROR_SUCCESS) + { + RegDeleteKey(hHostRegKey, pEntry->pCacheKeyName); + } + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error creating key for CacheKeyName, status = %d\n", status); + } + + // Close host key + RegCloseKey(hHostRegKey); + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error creating key for host, status = %d\n", status); + } + + // Close CASA_Auth_Cache key + RegCloseKey(hCASARegKey); + } + else + { + DbgTrace(0, "-AddEntryToAuthCache- Error opening CASA Auth Cache Key, status = %d\n", status); + } + + // Either place the cache entry in our in-memory cache or + // free it depending on the status of the operations performed. + if (status == ERROR_SUCCESS) + { + // The entry was added to the cache, save it in + // our in-memory cache. + InsertHeadList(&authCacheListHead, &pEntry->listEntry); + } + else + { + // Not able to successfully add the entry to the cache, + // free the entry. + FreeAuthCacheEntry(pEntry); + } + + DbgTrace(1, "-AddEntryToAuthCache- End\n", 0); +} + + +//++======================================================================= +CasaStatus +InitializeAuthCache(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + PSID pEveryoneSID; + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; + + DbgTrace(1, "-InitializeAuthCache- Start\n", 0); + + // Initialize the cache list head + InitializeListHead(&authCacheListHead); + + // Lets create the CASA Auth Cache registry key in the + // user's hive and limit access to it. + // + // Create a well-known SID for the Everyone group. + if (AllocateAndInitializeSid(&SIDAuthWorld, + 1, + SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, + &pEveryoneSID)) + { + EXPLICIT_ACCESS ea[3] = {0}; + SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; + PSID pAdminSID; + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will revoke Everyone access to the key. + ea[0].grfAccessPermissions = KEY_ALL_ACCESS; + ea[0].grfAccessMode = REVOKE_ACCESS; + ea[0].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; + ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID; + + // Create a SID for the BUILTIN\Administrators group. + if (AllocateAndInitializeSid(&SIDAuthNT, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &pAdminSID)) + { + DWORD status; + PACL pACL; + HANDLE hToken; + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will revoke the Administrators group access to the key. + ea[1].grfAccessPermissions = KEY_ALL_ACCESS; + ea[1].grfAccessMode = REVOKE_ACCESS; + ea[1].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; + ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; + ea[1].Trustee.ptstrName = (LPTSTR) pAdminSID; + + // Create a SID for the interactive user, first get the process token + if (OpenProcessToken(GetCurrentProcess(), + TOKEN_QUERY, + &hToken)) + { + char tokenInformation[1024]; + DWORD infoLength; + + if (GetTokenInformation(hToken, + TokenUser, + tokenInformation, + sizeof(tokenInformation), + &infoLength)) + { + TOKEN_USER *pTokenUser = (TOKEN_USER*) tokenInformation; + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will grant the interactive user access to the key. + ea[2].grfAccessPermissions = KEY_ALL_ACCESS; + ea[2].grfAccessMode = SET_ACCESS; + ea[2].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; + ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[2].Trustee.TrusteeType = TRUSTEE_IS_USER; + ea[2].Trustee.ptstrName = (LPTSTR) pTokenUser->User.Sid; + + // Create a new ACL that contains the new ACEs. + status = SetEntriesInAcl(3, ea, NULL, &pACL); + if (status == ERROR_SUCCESS) + { + PSECURITY_DESCRIPTOR pSD; + + // Allocate space for a security descriptor + pSD = (SECURITY_DESCRIPTOR*) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + if (pSD) + { + // Initialize a security descriptor + if (InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) + { + // Add the ACL to the security descriptor + if (SetSecurityDescriptorDacl(pSD, + TRUE, // bDaclPresent flag + pACL, + FALSE)) // not a default DACL + { + SECURITY_ATTRIBUTES sa; + HKEY hCASARegKey; + DWORD disposition; + + // Initialize a security attributes structure + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = pSD; + sa.bInheritHandle = FALSE; + + // Now create the CASA Auth Cache registry key for this user + // with the required access control restrictions. + status = RegCreateKeyExA(HKEY_CURRENT_USER, + CASA_AUTH_CACHE_REG_KEY, + 0, + NULL, + REG_OPTION_VOLATILE, + KEY_ALL_ACCESS, + &sa, + &hCASARegKey, + &disposition); + if (status == ERROR_SUCCESS) + { + // Success + retStatus = CASA_STATUS_SUCCESS; + + // Close CASA_Auth_Cache key + RegCloseKey(hCASARegKey); + } + else + { + DbgTrace(0, "-InitializeAuthCache- Error creating CASA Key, status = %d\n", status); + } + } + else + { + DbgTrace(0, "-InitializeAuthCache- SetSecurityDescriptorDacl Error = %d\n", GetLastError()); + } + } + else + { + DbgTrace(0, "-InitializeAuthCache- InitializeSecurityDescriptor Error %d\n", GetLastError()); + } + + // Free the space allocated for the security descriptor + LocalFree(pSD); + } + else + { + DbgTrace(0, "-InitializeAuthCache- Unable to allocate memory for SD\n", 0); + } + + // Free the ACL structure + LocalFree(pACL); + } + else + { + DbgTrace(0, "-InitializeAuthCache- SetEntriesInAcl Error %d\n", status); + } + } + else + { + DbgTrace(0, "-InitializeAuthCache- Error obtaining token information, error = %d\n", GetLastError()); + } + + // Release the process token handle + CloseHandle(hToken); + } + else + { + DbgTrace(0, "-InitializeAuthCache- Unable to obtain process token, error = %d\n", GetLastError()); + } + + // Free the SID for the administrator + FreeSid(pAdminSID); + } + else + { + DbgTrace(0, "-InitializeAuthCache- AllocateAndInitializeSid Error %d\n", GetLastError()); + } + + // Free the SID for everyone + FreeSid(pEveryoneSID); + } + else + { + DbgTrace(0, "-InitializeAuthCache- AllocateAndInitializeSid Error = %d\n", GetLastError()); + } + + DbgTrace(1, "-InitializeAuthCache- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + diff --git a/auth_token/client/win32/dllsup.c b/auth_token/client/win32/dllsup.c new file mode 100644 index 00000000..f6d3da15 --- /dev/null +++ b/auth_token/client/win32/dllsup.c @@ -0,0 +1,132 @@ +/*********************************************************************** + * + * 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" + +//===[ External data ]===================================================== + +//===[ Manifest constants ]================================================ + +//===[ Type definitions ]================================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +UINT32 g_ulCount = 0; +UINT32 g_ulLock = 0; +HANDLE g_hModule; + + +//++======================================================================= +BOOL APIENTRY DllMain( + HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +//=======================================================================-- +{ + BOOL retStatus = TRUE; + + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + { + g_hModule = hModule; + + // Initialize the library + if (InitializeLibrary() != 0) + { + // Failed to initialize the library + OutputDebugString("CASAAUTH -DllMain- Library initialization failed\n"); + retStatus = FALSE; + } + break; + } + + case DLL_THREAD_ATTACH: + { + g_hModule = hModule; + break; + } + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + { + /* Don't uninitialize on windows + tbd + */ + break; + } + } + + return retStatus; +} + +//++======================================================================= +// +// DllCanUnloadNow +// +// Synopsis +// +// +STDAPI +DllCanUnloadNow() +// +// Input Arguments +// +// Ouput Arguments +// +// Return Value +// S_OK The DLL can be unloaded. +// S_FALSE The DLL cannot be unloaded now. +// +// Description +// An Exported Function. +// DLLs that support the OLE Component Object Model (COM) should implement +// and export DllCanUnloadNow. +// A call to DllCanUnloadNow determines whether the DLL from which it is +// exported is still in use. A DLL is no longer in use when it is not +// managing any existing objects (the reference count on all of its objects +// is 0). +// DllCanUnloadNow returns S_FALSE if there are any existing references to +// objects that the DLL manages. +// +// Environment +// +// See Also +// +//=======================================================================-- +{ + // tbd + return ((g_ulCount == 0 && g_ulLock == 0) ? S_OK : S_FALSE); +} + +//========================================================================= +//========================================================================= + diff --git a/auth_token/client/win32/platform.h b/auth_token/client/win32/platform.h new file mode 100644 index 00000000..25d60544 --- /dev/null +++ b/auth_token/client/win32/platform.h @@ -0,0 +1,106 @@ +/*********************************************************************** + * + * 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 +#include +#include +#include +#include +#include +#include + +//===[ Type definitions ]================================================== + +#ifndef CONTAINING_RECORD +#define CONTAINING_RECORD(address, type, field) ((type *)( \ + (char*)(address) - \ + (char*)(&((type *)0)->field))) +#endif + +// +// DbgTrace macro define +// +#define DbgTrace(LEVEL, X, Y) { \ +char printBuff[256]; \ + if (LEVEL == 0) \ + { \ + _snprintf(printBuff, sizeof(printBuff), X, Y); \ + printf("AuthToken %s", printBuff); \ + } \ + else if (DebugLevel >= LEVEL) \ + { \ + _snprintf(printBuff, sizeof(printBuff), X, Y); \ + printf("AuthToken %s", printBuff); \ + } \ +} + + +#define bool BOOLEAN +#define true TRUE +#define false FALSE + +// +// Auth Cache Entry definition +// +typedef struct _AuthCacheEntry +{ + LIST_ENTRY listEntry; + DWORD creationTime; + DWORD expirationTime; + char *pHostName; + char *pCacheKeyName; + char *pToken; + int status; + +} AuthCacheEntry, *PAuthCacheEntry; + +// +// Rpc Session definition +// +typedef struct _RpcSession +{ + HINTERNET hSession; + HINTERNET hConnection; + +} RpcSession, *PRpcSession; + +// +// Other definitions +// +#define LIB_HANDLE HMODULE + + +//===[ Inlines functions ]=============================================== + +//===[ Function prototypes ]=============================================== + +//===[ Global externals ]================================================== + +//===[ External prototypes ]=============================================== + +//========================================================================= + diff --git a/auth_token/client/win32/platutils.c b/auth_token/client/win32/platutils.c new file mode 100644 index 00000000..1a6abb4d --- /dev/null +++ b/auth_token/client/win32/platutils.c @@ -0,0 +1,544 @@ +/*********************************************************************** + * + * 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 ]================================================== + +// +// Normalized Host Name Cache Entry definition +// +typedef struct _NormalizedHostNameCacheEntry +{ + LIST_ENTRY listEntry; + char *pHostName; + char *pNormalizedHostName; + int buffLengthRequired; + +} NormalizedHostNameCacheEntry, *PNormalizedHostNameCacheEntry; + + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + +// Global synchronization mutex for the user +static +HANDLE hUserMutex; + +// Normalized host name cache list head +static +LIST_ENTRY normalizedHostNameCacheListHead; + +// Synchronization mutex for the normalized host name cache +static +HANDLE hNormalizedHostNameCacheMutex; + +// Authentication mechanism configuration file folder +char mechConfigFolder[] = "\\Program Files\\Novell\\Casa\\Etc\\Auth\\Mechanisms"; + +// Path separator +char pathCharString[] = "\\"; + + +//++======================================================================= +CasaStatus +CreateUserMutex(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + char *pUsername = NULL; + DWORD nameLength = 0; + + DbgTrace(1, "-CreateUserMutex- Start\n", 0); + + // Get the size of the buffer required to obtain the user name + GetUserName(pUsername, &nameLength); + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { + // Allocate buffer to hold the user name + pUsername = (char*) malloc(nameLength); + if (pUsername) + { + // Get the name of the user + if (GetUserName(pUsername, &nameLength)) + { + SECURITY_ATTRIBUTES mutexAttributes; + char mutexName[256]; + + //printf("\nUsername is %s", pUsername); + + // Now lets create a global semaphore for the + // user and allow its handle to be inherited. + mutexAttributes.nLength = sizeof(mutexAttributes); + mutexAttributes.lpSecurityDescriptor = NULL; + mutexAttributes.bInheritHandle = TRUE; + if (sprintf(mutexName, "Global\\CASA_Auth_Mutex_%s", pUsername) != -1) + { + hUserMutex = CreateMutex(&mutexAttributes, + FALSE, + mutexName); + if (hUserMutex == NULL) + { + DbgTrace(0, "-CreateUserMutex- CreteMutex failed, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-CreateUserMutex- sprintf failed, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-CreateUserMutex- GetUserName failed, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Free the buffer allocated to hold the user name + free(pUsername); + } + else + { + DbgTrace(0, "-CreateUserMutex- Buffer allocation error\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + DbgTrace(0, "-CreateUserMutex- Un-expected GetUserName error, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + DbgTrace(1, "-CreateUserMutex- End, retStatus\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +void +LockUserMutex(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + DbgTrace(2, "-LockUserMutex- Start\n", 0); + + WaitForSingleObject(hUserMutex, INFINITE); + + DbgTrace(2, "-LockUserMutex- End\n", 0); +} + + +//++======================================================================= +void +FreeUserMutex(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + DbgTrace(2, "-FreeUserMutex- Start\n", 0); + + if (ReleaseMutex(hUserMutex) == 0) + { + DbgTrace(0, "-FreeUserMutex- ReleaseMutex failed, error = %d\n", GetLastError()); + } + + DbgTrace(2, "-FreeUserMutex- End\n", 0); +} + + +//++======================================================================= +LIB_HANDLE +OpenLibrary( + IN char *pFileName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + LIB_HANDLE libHandle; + + + DbgTrace(1, "-OpenLibrary- Start\n", 0); + + libHandle = LoadLibrary(pFileName); + if (libHandle == NULL) + { + DbgTrace(0, "-OpenLibrary- Not able to load library, error = %d\n", GetLastError()); + } + + DbgTrace(1, "-OpenLibrary- End, handle = %08X\n", libHandle); + + return libHandle; +} + + +//++======================================================================= +void +CloseLibrary( + IN LIB_HANDLE libHandle) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + DbgTrace(1, "-CloseLibrary- Start\n", 0); + + FreeLibrary(libHandle); + + DbgTrace(1, "-CloseLibrary- End\n", 0); +} + + +//++======================================================================= +void* +GetFunctionPtr( + IN LIB_HANDLE libHandle, + IN char *pFunctionName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + void *pFuncPtr; + + DbgTrace(1, "-GetFunctionPtr- Start\n", 0); + + pFuncPtr = GetProcAddress(libHandle, pFunctionName); + if (pFuncPtr == NULL) + { + DbgTrace(0, "-GetFunctionPtr- Not able to obtain func ptr, error = %d\n", GetLastError()); + } + + DbgTrace(1, "-GetFunctionPtr- End, pFuncPtr = %08X\n", pFuncPtr); + + return pFuncPtr; +} + + +//++======================================================================= +char* +NormalizeHostName( + IN char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + char *pNormalizedName = NULL; + LIST_ENTRY *pListEntry; + NormalizedHostNameCacheEntry *pEntry = NULL; + + DbgTrace(1, "-NormalizeHostName- Start\n", 0); + + // Obtain our synchronization mutex + WaitForSingleObject(hNormalizedHostNameCacheMutex, INFINITE); + + // First try to find an entry in the normalized host name cache + // for the host name provided. + pListEntry = normalizedHostNameCacheListHead.Flink; + while (pListEntry != &normalizedHostNameCacheListHead) + { + // Get pointer to the entry + pEntry = CONTAINING_RECORD(pListEntry, NormalizedHostNameCacheEntry, listEntry); + + // Check if the entry is for the host name + if (strcmp(pHostName, pEntry->pHostName) == 0) + { + // This entry corresponds to the given host name + break; + } + else + { + // The entry does not correspond to the given host name + pEntry = NULL; + } + + // Advance to the next entry + pListEntry = pListEntry->Flink; + } + + // Check if we found an entry in our cache for the given host name + if (pEntry) + { + // Entry found, obtain the normalized name from it. + pNormalizedName = (char*) malloc(pEntry->buffLengthRequired); + if (pNormalizedName) + { + // Copy the normalized name onto the allocated buffer + strcpy(pNormalizedName, pEntry->pNormalizedHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + else + { + // An entry was not found in our cache, create one. + pEntry = (NormalizedHostNameCacheEntry*) malloc(sizeof(NormalizedHostNameCacheEntry)); + if (pEntry) + { + // Zero the entry + memset(pEntry, 0, sizeof(*pEntry)); + + // Allocate a buffer to hold the host name in the entry + pEntry->pHostName = (char*) malloc(strlen(pHostName) + 1); + if (pEntry->pHostName) + { + struct hostent *pLookupResult; + struct sockaddr_in sockAddr = {0}; + + // Copy the host name given into the allocated buffer + strcpy(pEntry->pHostName, pHostName); + + // Now try to resolve the normalized name + pLookupResult = gethostbyname(pHostName); + if (pLookupResult && pLookupResult->h_addrtype == AF_INET) + { + char dnsHostName[NI_MAXHOST]; + + // Set up a sockaddr structure + sockAddr.sin_family = AF_INET; + sockAddr.sin_addr.S_un.S_addr = *((int*) pLookupResult->h_addr_list[0]); + + // Now try to resolve the name using DNS + if (getnameinfo((const struct sockaddr*) &sockAddr, + sizeof(sockAddr), + dnsHostName, + sizeof(dnsHostName), + NULL, + 0, + NI_NAMEREQD) == 0) + { + // We resolved the address to a DNS name, use it as the normalized name. + pEntry->buffLengthRequired = (int) strlen(dnsHostName) + 1; + pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired); + if (pEntry->pNormalizedHostName) + { + // Copy the dns name + strcpy(pEntry->pNormalizedHostName, dnsHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + else + { + DbgTrace(0, "-NormalizeHostName- getnameInfo failed, error %d\n", WSAGetLastError()); + + // Not able to resolve the name in DNS, just use the host name as + // the normalized name. + pEntry->buffLengthRequired = (int) strlen(pHostName) + 1; + pEntry->pNormalizedHostName = (char*) malloc(pEntry->buffLengthRequired); + if (pEntry->pNormalizedHostName) + { + // Copy the host name + strcpy(pEntry->pNormalizedHostName, pHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + } + else + { + DbgTrace(0, "-NormalizeHostName- Name resolution failed, error = %d\n", WSAGetLastError()); + } + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + + // Free the space allocated for the entry + free(pEntry); + } + + // Proceed based on whether or not we normalized the name + if (pEntry->pNormalizedHostName) + { + // The name was normalized, save the entry in our cache. + InsertHeadList(&normalizedHostNameCacheListHead, &pEntry->listEntry); + + // Return the normalized name present in the entry + pNormalizedName = (char*) malloc(pEntry->buffLengthRequired); + if (pNormalizedName) + { + // Copy the normalized name onto the allocated buffer + strcpy(pNormalizedName, pEntry->pNormalizedHostName); + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + else + { + // The host name was not normalized, free allocated resources. + if (pEntry->pHostName) + free(pEntry->pHostName); + free(pEntry); + } + } + else + { + DbgTrace(0, "-NormalizeHostName- Buffer allocation error\n", 0); + } + } + + // Release our synchronization mutex + if (ReleaseMutex(hNormalizedHostNameCacheMutex) == 0) + { + DbgTrace(0, "-NormalizeHostName- ReleaseMutex failed, error\n", 0); + } + + DbgTrace(1, "-NormalizeHostName- End, pNormalizedName = %08X\n", pNormalizedName); + + return pNormalizedName; +} + + +//++======================================================================= +CasaStatus +InitializeHostNameNormalization(void) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L1 +//=======================================================================-- +{ + CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + int winsockStartupResult; + WSADATA winsockData; + + DbgTrace(1, "-InitializeHostNameNormalization- Start\n", 0); + + // Initialize winsock + if ((winsockStartupResult = WSAStartup(MAKEWORD(2,2), &winsockData)) == 0) + { + // Initialize the cache list head + InitializeListHead(&normalizedHostNameCacheListHead); + + // Create a cache mutex only applicable to the current process + hNormalizedHostNameCacheMutex = CreateMutex(NULL, + FALSE, + NULL); + if (hNormalizedHostNameCacheMutex != NULL) + { + retStatus = CASA_STATUS_SUCCESS; + } + else + { + DbgTrace(0, "-InitializeHostNameNormalization- CreateMutex failed, error = %d\n", GetLastError()); + } + } + else + { + DbgTrace(0, "-InitializeHostNameNormalization- WSAStartup failed, error = %d\n", winsockStartupResult); + } + + DbgTrace(1, "-InitializeHostNameNormalization- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + diff --git a/auth_token/client/win32/rpc.c b/auth_token/client/win32/rpc.c new file mode 100644 index 00000000..d64fc029 --- /dev/null +++ b/auth_token/client/win32/rpc.c @@ -0,0 +1,442 @@ +/*********************************************************************** + * + * 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 ]================================================== + +#define INITIAL_RESPONSE_DATA_BUF_SIZE 1028 +#define INCREMENT_RESPONSE_DATA_BUF_SIZE 256 + +//===[ Function prototypes ]=============================================== + +//===[ Global variables ]================================================== + + +//++======================================================================= +static +CasaStatus +CopyMultiToWideAlloc( + IN char *pMulti, + IN int multiSize, + INOUT LPWSTR *ppWide, + INOUT int *pWideSize) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + int retStatus; + int size, i; + + DbgTrace(2, "-CopyMultiToWideAlloc- Start\n", 0); + + size = (multiSize + 1) * sizeof(WCHAR); + + if ((*ppWide = (PWCHAR) malloc(size)) != NULL) + { + for (i = 0; i < multiSize; i++) + { + *(*ppWide + i) = (unsigned char) *(pMulti + i); + } + + *(*ppWide + i) = L'\0'; + + if (pWideSize) + { + *pWideSize = size - sizeof(WCHAR); + } + + retStatus = CASA_STATUS_SUCCESS; + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + + DbgTrace(2, "-CopyMultiToWideAlloc- End, retStatus = %08X\n", retStatus); + + return retStatus; +} + + +//++======================================================================= +RpcSession* +OpenRpcSession( + IN char *pHostName) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + RpcSession *pSession; + + DbgTrace(1, "-OpenRpcSession- Start\n", 0); + + // Allocate space for the session + pSession = (RpcSession*) malloc(sizeof(*pSession)); + if (pSession) + { + // Zero the session structure + memset(pSession, 0, sizeof(*pSession)); + + // Open a Winhttp session + pSession->hSession = WinHttpOpen(L"CASA Client/1.0", + WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, + WINHTTP_NO_PROXY_NAME, + WINHTTP_NO_PROXY_BYPASS, + 0); + if (pSession->hSession) + { + LPWSTR pWideHostName; + int wideHostLen; + + // Session opened, now convert the host name to Unicode so that + // we can open a connection. + if (CopyMultiToWideAlloc(pHostName, + (int) strlen(pHostName), + &pWideHostName, + &wideHostLen) == CASA_STATUS_SUCCESS) + { + // Now open connection + pSession->hConnection = WinHttpConnect(pSession->hSession, + pWideHostName, + 8080, /*INTERNET_DEFAULT_HTTP_PORT,*/ + 0); + if (pSession->hConnection == NULL) + { + DbgTrace(0, "-OpenRpcSession- Failed to open connection, error = %d\n", GetLastError()); + + // Free allocated resources + WinHttpCloseHandle(pSession->hSession); + free(pSession); + pSession = NULL; + } + + // Free the host name wide string buffer + free(pWideHostName); + } + else + { + DbgTrace(0, "-OpenRpcSession- Error converting host name to wide string\n", 0); + + // Free allocated resources + WinHttpCloseHandle(pSession->hSession); + free(pSession); + pSession = NULL; + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Failed to open session, error = %d\n", GetLastError()); + } + } + else + { + DbgTrace(0, "-OpenRpcSession- Failed to allocate buffer for rpc session\n", 0); + } + + DbgTrace(2, "-OpenRpcSession- End, pSession = %08X\n", pSession); + + return pSession; +} + + +//++======================================================================= +void +CloseRpcSession( + IN RpcSession *pSession) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + DbgTrace(1, "-CloseRpcSession- Start\n", 0); + + // Close the connection handle + WinHttpCloseHandle(pSession->hConnection); + + // Close the session handle + WinHttpCloseHandle(pSession->hSession); + + // Free the space allocated for the session + free(pSession); + + DbgTrace(1, "-CloseRpcSession- End\n", 0); +} + + +//++======================================================================= +CasaStatus +Rpc( + IN RpcSession *pSession, + IN char *pMethod, + IN bool secure, + IN char *pRequestData, + INOUT char **ppResponseData, + INOUT int *pResponseDataLen) +// +// Arguments: +// +// Returns: +// +// Abstract: +// +// Notes: +// +// L0 +//=======================================================================-- +{ + CasaStatus retStatus = CASA_STATUS_SUCCESS; + char rpcTarget[256]; + LPWSTR pWideRpcTarget; + int wideRpcTargetLen; + WCHAR sendHeaders[] = L"Content-Type: text/html"; + + DbgTrace(1, "-Rpc- Start\n", 0); + + // Initialize output parameter + *ppResponseData = NULL; + + // Create rpc target string and convert it to a wide string + sprintf(rpcTarget, "CasaAuthServer/%s", pMethod); + retStatus = CopyMultiToWideAlloc(rpcTarget, + (int) strlen(rpcTarget), + &pWideRpcTarget, + &wideRpcTargetLen); + if (CASA_SUCCESS(retStatus)) + { + HINTERNET hRequest; + + // tbd - Add retry capability + + // Open a request handle + hRequest = WinHttpOpenRequest(pSession->hConnection, + L"POST", + pWideRpcTarget, + NULL, + WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, + secure? WINHTTP_FLAG_REFRESH | WINHTTP_FLAG_SECURE : WINHTTP_FLAG_REFRESH); + if (hRequest) + { + int reqDataLen = (int) strlen(pRequestData); + + // Send the request + if (WinHttpSendRequest(hRequest, + sendHeaders, + -1, + pRequestData, + reqDataLen, + reqDataLen, + 0)) + { + // Request sent, now await for the response. + if (WinHttpReceiveResponse(hRequest, NULL)) + { + WCHAR httpCompStatus[4] = {0}; + DWORD httpCompStatusLen = sizeof(httpCompStatus); + + // Response received, make sure that it completed successfully. + if (WinHttpQueryHeaders(hRequest, + WINHTTP_QUERY_STATUS_CODE, + NULL, + &httpCompStatus, + &httpCompStatusLen, + WINHTTP_NO_HEADER_INDEX)) + { + // Check that the request completed successfully + if (memcmp(httpCompStatus, L"200", sizeof(httpCompStatus)) == 0) + { + char *pResponseData; + int responseDataBufSize = INITIAL_RESPONSE_DATA_BUF_SIZE; + int responseDataRead = 0; + + // Now read the response data, to do so we need to allocate a buffer. + pResponseData = (char*) malloc(INITIAL_RESPONSE_DATA_BUF_SIZE); + if (pResponseData) + { + char *pCurrLocation = pResponseData; + DWORD bytesRead; + + do + { + bytesRead = 0; + if (WinHttpReadData(hRequest, + (LPVOID) pCurrLocation, + responseDataBufSize - responseDataRead, + &bytesRead)) + { + pCurrLocation += bytesRead; + responseDataRead += bytesRead; + + // Check if we need to allocate a larger buffer + if (responseDataRead == responseDataBufSize) + { + char *pTmpBuf; + + // We need to upgrade the receive buffer + pTmpBuf = (char*) malloc(responseDataBufSize + INCREMENT_RESPONSE_DATA_BUF_SIZE); + if (pTmpBuf) + { + memcpy(pTmpBuf, pResponseData, responseDataBufSize); + free(pResponseData); + pResponseData = pTmpBuf; + pCurrLocation = pResponseData + responseDataBufSize; + responseDataBufSize += INCREMENT_RESPONSE_DATA_BUF_SIZE; + } + else + { + DbgTrace(0, "-Rpc- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + } + else + { + DbgTrace(0, "-Rpc- Failed reading response data, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } while (CASA_SUCCESS(retStatus) + && bytesRead != 0); + + // Check if the response data was successfully received + if (CASA_SUCCESS(retStatus)) + { + // The response data was received, return it to the caller. + *ppResponseData = pResponseData; + *pResponseDataLen = responseDataRead; + } + else + { + // Failed to receive the response data, free the allocated buffer. + free(pResponseData); + } + } + else + { + DbgTrace(0, "-Rpc- Buffer allocation failure\n", 0); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_INSUFFICIENT_RESOURCES); + } + } + else + { + DbgTrace(0, "-Rpc- HTTP request did not complete successfully, status = %S\n", httpCompStatus); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-Rpc- Unable to obtain http request completion status, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + DbgTrace(0, "-Rpc- Unable to receive response, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + else + { + int error = GetLastError(); + + DbgTrace(0, "-Rpc- Unsuccessful send http request, error = %d\n", error); + if (error == ERROR_WINHTTP_CANNOT_CONNECT) + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_AUTH_SERVER_UNAVAILABLE); + } + else + { + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + } + + // Close the request handle + WinHttpCloseHandle(hRequest); + } + else + { + DbgTrace(0, "-Rpc- Unable to open http request, error = %d\n", GetLastError()); + retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, + CASA_FACILITY_AUTHTOKEN, + CASA_STATUS_UNSUCCESSFUL); + } + + // Free the rpc target wide string buffer + free(pWideRpcTarget); + } + else + { + DbgTrace(0, "-Rpc- Error converting method name to wide string\n", 0); + } + + DbgTrace(1, "-Rpc- End, retStatus = %d\n", retStatus); + + return retStatus; +} + +