2006-11-13 05:05:01 +01:00
/***********************************************************************
*
* 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"
2006-12-08 06:45:03 +01:00
//#define INT32_MAX 2147483647
2006-11-13 05:05:01 +01:00
//===[ 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 (
2006-12-08 06:45:03 +01:00
IN const char * pServiceName ,
IN const char * pTokenBuf ,
2007-02-06 23:52:44 +01:00
IN const size_t tokenBufLen ,
2006-12-08 06:45:03 +01:00
INOUT PrincipalIf * * ppPrincipalIf )
2006-11-13 05:05:01 +01:00
//
// 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 ;
2007-02-06 23:52:44 +01:00
uint32_t decodedTokenBufLen ;
2006-11-13 05:05:01 +01:00
PrincipalIf * pPrincipalIf ;
DbgTrace ( 1 , " -ValidateAuthToken- Start \n " , 0 ) ;
// Validate input parameters
if ( pServiceName = = NULL
| | pTokenBuf = = NULL
| | tokenBufLen = = 0
2007-02-06 23:52:44 +01:00
| | tokenBufLen > UINT32_MAX
| | tokenBufLen = = 0
2006-11-13 05:05:01 +01:00
| | 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 ) ;
2006-11-13 05:05:01 +01:00
}
else
{
if ( ( g_ipcInitPtr ) ( " CASA_AuthTokenValidate " ,
g_multiThreadedApplication ,
DebugLevel ,
2006-12-08 11:26:52 +01:00
true ) = = 0 )
2006-11-13 05:05:01 +01:00
{
// 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 ) ;
2006-11-13 05:05:01 +01:00
}
}
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 ) ;
2006-11-13 05:05:01 +01:00
}
}
}
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 ) )
{
2007-02-06 23:52:44 +01:00
char * pIdenTokenData ;
uint32_t idenTokenDataLen ;
2006-11-13 05:05:01 +01:00
// 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.
2007-02-06 23:52:44 +01:00
& 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.
2006-11-13 05:05:01 +01:00
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 :
2006-12-08 06:45:03 +01:00
DbgTrace ( 1 , " -ValidateAuthToken- End, retStatus = %0X \n " , retStatus ) ;
2006-11-13 05:05:01 +01:00
return retStatus ;
}
//++=======================================================================
static void __attribute__ ( ( constructor ) )
so_init ( )
//
// Arguments In: None.
//
// Arguments Out: None.
//
// Returns: Nothing.
//
// Abstract: Library initialization routine.
//
// L2
//=======================================================================--
{
2006-12-08 06:45:03 +01:00
// Check for environment variable specifying that the application
// is not multi-threaded.
2006-11-13 05:05:01 +01:00
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 ) ( ) ;
}
//++=======================================================================
//++=======================================================================
//++=======================================================================