CASA/CASA-auth-token/server/AuthTokenValidate/validate.c

420 lines
16 KiB
C
Raw Normal View History

/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
//===[ Include files ]=====================================================
#include "internal.h"
//===[ Manifest constants ]================================================
#define APPLICATION_NOT_MULTI_THREADED "CASA_APPLICATION_NOT_MULTI_THREADED"
#define DOMAIN_SOCKET_FILE_NAME "/var/lib/CASA/authtoken/validate/socket"
//#define INT32_MAX 2147483647
//===[ 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 size_t 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;
uint32_t decodedTokenBufLen;
PrincipalIf *pPrincipalIf;
DbgTrace(1, "-ValidateAuthToken- Start\n", 0);
// Validate input parameters
if (pServiceName == NULL
|| pTokenBuf == NULL
|| tokenBufLen == 0
|| tokenBufLen > UINT32_MAX
|| 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();
2006-12-08 11:26:52 +01:00
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
else
{
if ((g_ipcInitPtr)("CASA_AuthTokenValidate",
g_multiThreadedApplication,
DebugLevel,
2006-12-08 11:26:52 +01:00
true) == 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();
2006-12-08 11:26:52 +01:00
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
}
else
{
DbgTrace(0, "-ValidateAuthToken- Ipc subsystem initialization failed\n", 0);
(g_ipcShutdownPtr)();
IdenTokenUninit();
PrincipalIfUninit();
ConfigIfUninit();
2006-12-08 11:26:52 +01:00
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
CASA_FACILITY_AUTHTOKEN,
CASA_STATUS_UNSUCCESSFUL);
}
}
}
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;
uint32_t 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); // IMPORTANT: Protect against invalid token type names when this is implemented. Invalid token
// names would contain something like "../" as part of the string to try to get us to open an
// malicious token provider library.
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 = %0X\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 not 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)();
}
//++=======================================================================
//++=======================================================================
//++=======================================================================