/*********************************************************************** * * 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" //===[ Manifest constants ]================================================ #define APPLICATION_NOT_MULTI_THREADED "CASA_APPLICATION_NOT_MULTI_THREADED" #define DOMAIN_SOCKET_FILE_NAME "/var/lib/CASA/authtoken/validate/socket" //===[ Type definitions ]================================================== //===[ Function prototypes ]=============================================== //===[ Global variables ]================================================== // Debug Level int DebugLevel = 0; // // Initialization variables // static bool g_moduleInitialized = false; // // Configuration variables // bool g_multiThreadedApplication = true; // // IPC Client Sub-system variables // PFN_IpcClientInit g_ipcInitPtr = NULL; PFN_IpcClientShutdown g_ipcShutdownPtr = NULL; //PFN_IpcClientOpenInetRemoteEndPoint g_ipcOpenEndPointPtr = NULL; PFN_IpcClientOpenUnixRemoteEndPoint g_ipcOpenEndPointPtr = NULL; PFN_IpcClientCloseRemoteEndPoint g_ipcCloseEndPointPtr = NULL; PFN_IpcClientSubmitReq g_ipcSubmitReq = NULL; uint32_t g_atvsEndPointHandle; // Authentication Token Validation Service endpoint handle //++======================================================================= CasaStatus SSCS_CALL ValidateAuthToken( IN const char *pServiceName, IN const char *pTokenBuf, IN const int tokenBufLen, INOUT PrincipalIf **ppPrincipalIf) // // Arguments: // pServiceName - // Pointer to NULL terminated string that contains the // name of the service targeted by the token. // // 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. // // tokenBufLen - // Length of the data contained within the buffer pointed // at by pTokenBuf. // // ppPrincipalIf - // Pointer to variable that will receive a pointer to a principal // interface with information about the authenticated entity. // IMPORTANT NOTE: The caller is responsible for releasing the // interface after it is done with it to avoid a resource leak. // // Returns: // Casa status. // // Description: // Validates authentication token. // // L2 //=======================================================================-- { CasaStatus retStatus; char *pDecodedTokenBuf; int decodedTokenBufLen; PrincipalIf *pPrincipalIf; DbgTrace(1, "-ValidateAuthToken- Start\n", 0); // Validate input parameters if (pServiceName == NULL || pTokenBuf == NULL || tokenBufLen == 0 || ppPrincipalIf == NULL) { DbgTrace(0, "-ValidateAuthToken- Invalid input parameter\n", 0); retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_INVALID_PARAMETER); goto exit; } // Make sure that the module has been initialized if (g_moduleInitialized == false) { // The module has not been initialized, synchronize access thought this section // to avoid having two threads performing initialization. AcquireModuleMutex; // Assume success retStatus = CASA_STATUS_SUCCESS; // Check again in case another thread pre-empted us. if (g_moduleInitialized == false) { // Initialize the ConfigIf complex retStatus = ConfigIfInit(); if (CASA_SUCCESS(retStatus)) { // Initialize the PrincipalIf complex retStatus = PrincipalIfInit(); if (CASA_SUCCESS(retStatus)) { // Initialize the IdenToken complex retStatus = IdenTokenInit(); if (CASA_SUCCESS(retStatus)) { // Initialize the Client Ipc Subsystem // // First load the library. We load it itself to keep the system // from unloading it in-case that the application unloads us. Some // applications such as PAM application will repeateadly load and // unload us. void* libHandle = OpenLibrary(IpcClientLibraryPath); if (libHandle) { // The Ipc library has been loaded, now get the symbols that we need. g_ipcInitPtr = GetFunctionPtr(libHandle, "IpcClientInit"); g_ipcShutdownPtr = GetFunctionPtr(libHandle, "IpcClientShutdown"); //g_ipcOpenEndPointPtr = GetFunctionPtr(libHandle, "IpcClientOpenInetRemoteEndPoint"); g_ipcOpenEndPointPtr = GetFunctionPtr(libHandle, "IpcClientOpenUnixRemoteEndPoint"); g_ipcCloseEndPointPtr = GetFunctionPtr(libHandle, "IpcClientCloseRemoteEndPoint"); g_ipcSubmitReq = GetFunctionPtr(libHandle, "IpcClientSubmitReq"); if (g_ipcInitPtr == NULL || g_ipcShutdownPtr == NULL || g_ipcOpenEndPointPtr == NULL || g_ipcCloseEndPointPtr == NULL || g_ipcSubmitReq == NULL) { DbgTrace(0, "-ValidateAuthToken- Failed to get needed Ipc library function pointer\n", 0); IdenTokenUninit(); PrincipalIfUninit(); ConfigIfUninit(); } else { if ((g_ipcInitPtr)("CASA_AuthTokenValidate", g_multiThreadedApplication, DebugLevel, false) == 0) { // Open endpoint for the Authentication Token Validation Service //if ((g_ipcOpenEndPointPtr)(5000, // 0x7F000001, // 0, // &g_atvsEndPointHandle) == 0) if ((g_ipcOpenEndPointPtr)(DOMAIN_SOCKET_FILE_NAME, 0, &g_atvsEndPointHandle) == 0) { // Success g_moduleInitialized = true; } else { DbgTrace(0, "-ValidateAuthToken- Failed to open remote endpoint\n", 0); (g_ipcShutdownPtr)(); IdenTokenUninit(); PrincipalIfUninit(); ConfigIfUninit(); } } else { DbgTrace(0, "-ValidateAuthToken- Ipc subsystem initialization failed\n", 0); (g_ipcShutdownPtr)(); IdenTokenUninit(); PrincipalIfUninit(); ConfigIfUninit(); } } } else { DbgTrace(0, "-ValidateAuthToken- Failed to load Ipc library, error = %s\n", dlerror()); } } else { PrincipalIfUninit(); ConfigIfUninit(); } } else { ConfigIfUninit(); } } } // Stop synchronization ReleaseModuleMutex; // Exit if we failed if (g_moduleInitialized == false) goto exit; } // First decode the token string retStatus = DecodeData(pTokenBuf, tokenBufLen, (void**) &pDecodedTokenBuf, &decodedTokenBufLen); if (CASA_SUCCESS(retStatus)) { char *pIdenTokenData; int idenTokenDataLen; // Assume failure retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR, CASA_FACILITY_AUTHTOKEN, CASA_STATUS_AUTHENTICATION_FAILURE); // Token was decoded successfully, now submit the authentication token to the // authentication token validation service. if ((g_ipcSubmitReq)(g_atvsEndPointHandle, pDecodedTokenBuf, decodedTokenBufLen, &pIdenTokenData, &idenTokenDataLen) == 0) { // The submit succeeded, make sure that we got some identity data back. if (pIdenTokenData) { if (idenTokenDataLen != 0) { IdenTokenProviderIf *pIdenTokenProviderIf; // The authentication token was validated, now obtain // Identity Token Provider interface. retStatus = GetIdenTokenProviderInterface("CasaIdentityToken", // tbd - Hard code until we enhance the protocol with the atvs to also return this information. &pIdenTokenProviderIf); if (CASA_SUCCESS(retStatus)) { IdenTokenIf *pIdenTokenIf; // Use the Identity Token Provider to get an Identity Token Interface instance retStatus = pIdenTokenProviderIf->getIdentityTokenIf(pIdenTokenProviderIf, pIdenTokenData, idenTokenDataLen, &pIdenTokenIf); if (CASA_SUCCESS(retStatus)) { // Now create a principal interface instance with the identity information present in // the identity token. retStatus = GetPrincipalInterface(pIdenTokenIf, &pPrincipalIf); if (CASA_SUCCESS(retStatus)) { // Success, return the principal interface to the caller. *ppPrincipalIf = pPrincipalIf; } else { DbgTrace(0, "-ValidateAuthToken- Failed to instantiate principal interface\n", 0); } // Release identity token interface pIdenTokenIf->releaseReference(pIdenTokenIf); } else { DbgTrace(0, "-ValidateAuthToken- Failed to instantiate identity token\n", 0); } // Release identity token provider interface pIdenTokenProviderIf->releaseReference(pIdenTokenProviderIf); } else { DbgTrace(0, "-ValidateAuthToken- Failed to obtain identity token provider interface\n", 0); } } else { DbgTrace(0, "-ValidateAuthToken- ValidateAuthToken submit did not return identity token data\n", 0); } // Free the buffer containing the identity token data free(pIdenTokenData); } else { DbgTrace(0, "-ValidateAuthToken- ValidateAuthToken submit did not return identity token data buffer\n", 0); } } else { DbgTrace(1, "-ValidateAuthToken- ValidateAuthToken submit failed\n", 0); } // Free the decoded token buffer free(pDecodedTokenBuf); } else { DbgTrace(0, "-ValidateAuthToken- Token decode failure\n", 0); } exit: DbgTrace(1, "-ValidateAuthToken- End, retStatus = %08X\n", retStatus); return retStatus; } //++======================================================================= static void __attribute__((constructor)) so_init() // // Arguments In: None. // // Arguments Out: None. // // Returns: Nothing. // // Abstract: Library initialization routine. // // L2 //=======================================================================-- { // Check for environment variable specifying that the application is // multi-threaded. if (getenv(APPLICATION_NOT_MULTI_THREADED) != NULL) { // The parameter has been configured, remember it. g_multiThreadedApplication = false; } } //++======================================================================= static void __attribute__((destructor)) so_fini() // // Arguments In: None. // // Arguments Out: None. // // Returns: Nothing. // // Abstract: Library un-initialization routine. // // L2 //=======================================================================-- { if (g_ipcShutdownPtr) (g_ipcShutdownPtr)(); } //++======================================================================= //++======================================================================= //++=======================================================================