401 lines
14 KiB
C
401 lines
14 KiB
C
|
/***********************************************************************
|
||
|
*
|
||
|
* 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"
|
||
|
|
||
|
//===[ 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)();
|
||
|
}
|
||
|
|
||
|
|
||
|
//++=======================================================================
|
||
|
//++=======================================================================
|
||
|
//++=======================================================================
|
||
|
|