2006-11-13 06:20:43 +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"
//===[ Type definitions ]==================================================
# define DEFAULT_RETRY_LIFETIME 5 // seconds
2007-03-05 07:48:26 +01:00
# define LOG_FILE_NAME "\\casaauthtoken.log"
2007-01-12 13:49:25 +01:00
2006-11-13 06:20:43 +01:00
//===[ Function prototypes ]===============================================
int
InitializeLibrary ( void ) ;
//===[ Global variables ]==================================================
//
2007-03-05 07:48:26 +01:00
// Debug tracing level and debug log file path.
//
2006-11-13 06:20:43 +01:00
int DebugLevel = 0 ;
2007-03-05 07:48:26 +01:00
char * g_pDebugLogFilePath = NULL ;
2006-11-13 06:20:43 +01:00
//
// Operating parameter
//
bool g_bInitialized = false ;
long g_rpcFlags = SECURE_RPC_FLAG | ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG ;
char * g_pATSHostName = NULL ;
uint16_t g_ATSPort = 2645 ;
//++=======================================================================
static
CasaStatus
ObtainSessionToken (
IN RpcSession * pRpcSession ,
IN AuthPolicy * pAuthPolicy ,
IN const char * pHostName ,
IN void * pCredStoreScope ,
2007-01-29 11:46:18 +01:00
INOUT char * * ppSessionToken ,
INOUT AuthContext * * ppSessionTokenAuthContext )
2006-11-13 06:20:43 +01:00
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
CasaStatus retStatus = CasaStatusBuild ( CASA_SEVERITY_ERROR ,
CASA_FACILITY_AUTHTOKEN ,
CASA_STATUS_UNSUCCESSFUL ) ;
LIST_ENTRY * pListEntry ;
AuthCacheEntry * pCacheEntry = NULL ;
2007-02-03 00:02:43 +01:00
AuthContext * pAuthContext = NULL ;
2006-11-13 06:20:43 +01:00
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 )
{
// Get pointer to AuthContext structure
pAuthContext = CONTAINING_RECORD ( pListEntry , AuthContext , listEntry ) ;
// Try to find a cache entry for the auth context
pCacheEntry = FindSessionTokenEntryInCache ( pAuthContext - > pContext ,
pCredStoreScope ) ;
if ( pCacheEntry ! = NULL )
{
// Cache entry found, check if it is of use to us.
if ( CASA_SUCCESS ( pCacheEntry - > status ) )
{
// This entry can be used, stop looking.
retStatus = pCacheEntry - > status ;
break ;
}
else
{
2006-11-30 19:21:42 +01:00
// Free the entry
2006-11-13 06:20:43 +01:00
FreeAuthCacheEntry ( pCacheEntry ) ;
}
}
// 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 )
{
2007-01-29 11:46:18 +01:00
char * pAuthMechToken ;
2006-11-13 06:20:43 +01:00
// Get pointer to AuthContext structure
pAuthContext = CONTAINING_RECORD ( pListEntry , AuthContext , listEntry ) ;
// Only try to create cache entry for the auth context if there is not
// one already.
pCacheEntry = FindSessionTokenEntryInCache ( pAuthContext - > pContext ,
pCredStoreScope ) ;
if ( pCacheEntry = = NULL )
{
2007-02-03 00:02:43 +01:00
char * pReqMsg = NULL ;
char * pRespMsg = NULL ;
size_t respLen ;
2006-11-13 06:20:43 +01:00
// Get authentication mechanism token
retStatus = GetAuthMechToken ( pAuthContext ,
pHostName ,
pCredStoreScope ,
& 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 ;
}
2006-11-30 19:21:42 +01:00
// Authenticate to the ATS
pReqMsg = BuildAuthenticateMsg ( pAuthContext , pAuthMechToken ) ;
if ( pReqMsg )
2006-11-13 06:20:43 +01:00
{
2006-11-30 19:21:42 +01:00
// Issue rpc
retStatus = Rpc ( pRpcSession ,
" Authenticate " ,
g_rpcFlags ,
pReqMsg ,
& pRespMsg ,
& respLen ) ;
2006-11-13 06:20:43 +01:00
if ( CASA_SUCCESS ( retStatus ) )
{
2007-01-12 09:43:53 +01:00
if ( pRespMsg
& & respLen ! = 0 )
2006-11-30 19:21:42 +01:00
{
2007-01-12 09:43:53 +01:00
AuthenticateResp * pAuthenticateResp ;
// Create Authenticate response object
retStatus = CreateAuthenticateResp ( pRespMsg , respLen , & pAuthenticateResp ) ;
if ( CASA_SUCCESS ( retStatus ) )
{
// Return the auth token to the caller
pCacheEntry = CreateSessionTokenCacheEntry ( pAuthContext - > pContext ,
retStatus ,
pAuthenticateResp - > pToken ,
pAuthenticateResp - > tokenLifetime ,
pCredStoreScope ) ;
pAuthenticateResp - > pToken = NULL ; // To keep us from freeing the buffer
// Free the Authenticate response object
RelAuthenticateResp ( pAuthenticateResp ) ;
}
}
else
{
DbgTrace ( 0 , " -ObtainSessionToken- Did not receive Authenticate Response data \n " , 0 ) ;
2007-01-12 13:49:25 +01:00
retStatus = CasaStatusBuild ( CASA_SEVERITY_ERROR ,
CASA_FACILITY_AUTHTOKEN ,
CASA_STATUS_SERVER_ERROR ) ;
2006-11-30 19:21:42 +01:00
}
}
else
{
DbgTrace ( 0 , " -ObtainSessionToken- Authenticate Rpc failure, error = %08X \n " , retStatus ) ;
2006-11-13 06:20:43 +01:00
}
2006-11-30 19:21:42 +01:00
// Free resources that may be hanging around
if ( pRespMsg )
2007-01-04 11:18:40 +01:00
{
// Clear and free the memory associated with the response since it may contain
// security sensitive data.
memset ( pRespMsg , 0 , respLen ) ;
2006-11-30 19:21:42 +01:00
free ( pRespMsg ) ;
2007-01-04 11:18:40 +01:00
}
2006-12-01 13:42:52 +01:00
// Clear and free the memory associated with the request message since
2007-01-04 11:18:40 +01:00
// it may contain security sensitive information.
2006-12-01 13:42:52 +01:00
memset ( pReqMsg , 0 , strlen ( pReqMsg ) ) ;
2006-11-30 19:21:42 +01:00
free ( pReqMsg ) ;
2006-11-13 06:20:43 +01:00
}
else
{
2006-11-30 19:21:42 +01:00
DbgTrace ( 0 , " -ObtainSessionToken- Error building Authenticate msg \n " , 0 ) ;
retStatus = CasaStatusBuild ( CASA_SEVERITY_ERROR ,
2007-01-04 14:27:31 +01:00
CASA_FACILITY_AUTHTOKEN ,
CASA_STATUS_INSUFFICIENT_RESOURCES ) ;
2006-11-13 06:20:43 +01:00
}
2007-03-05 07:48:26 +01:00
// Add the entry to the cache if the reason that we failed was because
// the server was unavailable.
2006-11-30 19:21:42 +01:00
if ( CasaStatusCode ( retStatus ) = = CASA_STATUS_AUTH_SERVER_UNAVAILABLE )
{
pCacheEntry = CreateSessionTokenCacheEntry ( pAuthContext - > pContext ,
retStatus ,
NULL ,
DEFAULT_RETRY_LIFETIME ,
pCredStoreScope ) ;
}
// Release the cache entry if the resulting status is not successful
2007-01-04 14:27:31 +01:00
if ( pCacheEntry )
2006-11-30 19:21:42 +01:00
{
2007-01-04 14:27:31 +01:00
if ( ! CASA_SUCCESS ( retStatus ) )
{
FreeAuthCacheEntry ( pCacheEntry ) ;
}
2006-11-30 19:21:42 +01:00
}
2006-11-13 06:20:43 +01:00
// Free up the buffer associated with the authentication mechanism token
2006-12-01 13:42:52 +01:00
// after clearing it since it may contain sensitive information.
memset ( pAuthMechToken , 0 , strlen ( pAuthMechToken ) ) ;
2006-11-13 06:20:43 +01:00
free ( pAuthMechToken ) ;
}
else
{
2006-11-30 19:21:42 +01:00
// Free the entry
FreeAuthCacheEntry ( pCacheEntry ) ;
2006-11-13 06:20:43 +01:00
}
// 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 - > token ) + 1 ) ;
if ( * ppSessionToken )
{
// Copy the token onto the allocated buffer
strcpy ( * ppSessionToken , pCacheEntry - > token ) ;
2007-01-29 11:46:18 +01:00
// Return pointer to AuthContext associated with the session token
* ppSessionTokenAuthContext = pAuthContext ;
2006-11-13 06:20:43 +01:00
}
else
{
DbgTrace ( 0 , " -ObtainSessionToken- Buffer allocation failure \n " , 0 ) ;
retStatus = CasaStatusBuild ( CASA_SEVERITY_ERROR ,
CASA_FACILITY_AUTHTOKEN ,
CASA_STATUS_INSUFFICIENT_RESOURCES ) ;
}
FreeAuthCacheEntry ( pCacheEntry ) ;
}
DbgTrace ( 1 , " -ObtainSessionToken- End, retStatus = %08X \n " , retStatus ) ;
return retStatus ;
}
//++=======================================================================
static
CasaStatus
ObtainAuthTokenFromServer (
IN const char * pServiceName ,
IN const char * pHostName ,
2007-03-05 07:48:26 +01:00
IN const char * pNormalizedHostName ,
2007-04-03 00:16:07 +02:00
IN const void * pCredStoreScope ,
2006-11-13 06:20:43 +01:00
INOUT char * * ppAuthToken ,
INOUT int * pTokenLifetime ,
2007-04-03 00:16:07 +02:00
INOUT bool * pAdvisedToRetry )
2006-11-13 06:20:43 +01:00
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
CasaStatus retStatus = CASA_STATUS_SUCCESS ;
RpcSession * pRpcSession ;
DbgTrace ( 1 , " -ObtainAuthTokenFromServer- Start \n " , 0 ) ;
2007-04-03 00:16:07 +02:00
// Initialize output parameters
2006-11-13 06:20:43 +01:00
* ppAuthToken = NULL ;
2007-04-03 00:16:07 +02:00
* pAdvisedToRetry = false ;
2006-11-13 06:20:43 +01:00
// Open Rpc Session to the auth service at the specified host
pRpcSession = OpenRpcSession ( ( g_pATSHostName ! = NULL ) ? g_pATSHostName : pHostName ,
g_ATSPort ) ;
if ( pRpcSession )
{
char * pReqMsg = NULL ;
char * pRespMsg = NULL ;
2007-02-03 00:02:43 +01:00
size_t respLen ;
2006-11-13 06:20:43 +01:00
AuthPolicy * pAuthPolicy = NULL ;
GetAuthPolicyResp * pGetAuthPolicyResp = NULL ;
GetAuthTokenResp * pGetAuthTokenResp = NULL ;
char * pSessionToken = NULL ;
// Request the auth parameters associated with this service
pReqMsg = BuildGetAuthPolicyMsg ( pServiceName , " localhost " ) ; // tbd - This will be changed in the future so that we can support services residing in a different host than the ATS
if ( pReqMsg )
{
// Issue rpc
retStatus = Rpc ( pRpcSession ,
" GetAuthPolicy " ,
g_rpcFlags ,
pReqMsg ,
& pRespMsg ,
& respLen ) ;
if ( CASA_SUCCESS ( retStatus ) )
{
2007-01-12 09:43:53 +01:00
if ( pRespMsg
& & respLen ! = 0 )
2006-11-13 06:20:43 +01:00
{
2007-01-12 09:43:53 +01:00
// Create GetAuthPolicy response object
retStatus = CreateGetAuthPolicyResp ( pRespMsg , respLen , & pGetAuthPolicyResp ) ;
2006-11-13 06:20:43 +01:00
if ( CASA_SUCCESS ( retStatus ) )
{
2007-01-12 09:43:53 +01:00
// Create the AuthPolicy object
retStatus = CreateAuthPolicy ( pGetAuthPolicyResp - > pPolicy ,
pGetAuthPolicyResp - > policyLen ,
& pAuthPolicy ) ;
2006-11-13 06:20:43 +01:00
if ( CASA_SUCCESS ( retStatus ) )
{
2007-01-29 11:46:18 +01:00
AuthContext * pSessionTokenAuthContext = NULL ;
2007-01-12 09:43:53 +01:00
// Now try to obtain a session token
retStatus = ObtainSessionToken ( pRpcSession ,
pAuthPolicy ,
( g_pATSHostName ! = NULL ) ? g_pATSHostName : pHostName ,
pCredStoreScope ,
2007-01-29 11:46:18 +01:00
& pSessionToken ,
& pSessionTokenAuthContext ) ;
2007-01-12 09:43:53 +01:00
if ( CASA_SUCCESS ( retStatus ) )
2006-11-13 06:20:43 +01:00
{
2007-01-12 09:43:53 +01:00
// Request auth token for the service
free ( pReqMsg ) ;
pReqMsg = BuildGetAuthTokenMsg ( pServiceName , " localhost " , pSessionToken ) ; // tbd - This will be changed in the future so that we can support services residing in a different host than the ATS
if ( pReqMsg )
2006-11-13 06:20:43 +01:00
{
2007-01-12 09:43:53 +01:00
// Free the previous response msg buffer
free ( pRespMsg ) ;
pRespMsg = NULL ;
// Issue rpc
retStatus = Rpc ( pRpcSession ,
" GetAuthToken " ,
g_rpcFlags ,
pReqMsg ,
& pRespMsg ,
& respLen ) ;
2006-11-13 06:20:43 +01:00
if ( CASA_SUCCESS ( retStatus ) )
{
2007-01-12 09:43:53 +01:00
if ( pRespMsg
& & respLen ! = 0 )
{
// 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- Failed to create GetAuthTokenResp object, error = %08X \n " , retStatus ) ;
2007-01-29 11:46:18 +01:00
// Remove the session token from the cache in case that it was due to a bad session token
if ( pSessionTokenAuthContext )
{
RemoveSessionTokenEntryInCache ( pSessionTokenAuthContext - > pContext ,
pCredStoreScope ) ;
2007-04-03 00:16:07 +02:00
// Advice that a retry should be attempted
* pAdvisedToRetry = true ;
2007-01-29 11:46:18 +01:00
}
2007-01-12 09:43:53 +01:00
}
}
else
{
DbgTrace ( 0 , " -ObtainAuthTokenFromServer- Did not receive GetAuthToken Response data \n " , 0 ) ;
2007-01-12 13:49:25 +01:00
retStatus = CasaStatusBuild ( CASA_SEVERITY_ERROR ,
CASA_FACILITY_AUTHTOKEN ,
CASA_STATUS_SERVER_ERROR ) ;
2007-01-12 09:43:53 +01:00
}
2006-11-13 06:20:43 +01:00
}
else
{
2007-01-12 09:43:53 +01:00
DbgTrace ( 0 , " -ObtainAuthTokenFromServer- GetAuthToken Rpc failure, error = %08X \n " , retStatus ) ;
2007-01-12 13:49:25 +01:00
retStatus = CasaStatusBuild ( CASA_SEVERITY_ERROR ,
CASA_FACILITY_AUTHTOKEN ,
CASA_STATUS_SERVER_ERROR ) ;
2006-11-13 06:20:43 +01:00
}
}
else
{
2007-01-12 09:43:53 +01:00
DbgTrace ( 0 , " -ObtainAuthTokenFromServer- Error building GetAuthToken msg \n " , 0 ) ;
retStatus = CasaStatusBuild ( CASA_SEVERITY_ERROR ,
CASA_FACILITY_AUTHTOKEN ,
CASA_STATUS_INSUFFICIENT_RESOURCES ) ;
2006-11-13 06:20:43 +01:00
}
}
else
{
2007-01-12 09:43:53 +01:00
DbgTrace ( 0 , " -ObtainAuthTokenFromServer- Failed to obtain session token, error = %08X \n " , retStatus ) ;
2006-11-13 06:20:43 +01:00
}
}
else
{
2007-01-12 09:43:53 +01:00
DbgTrace ( 0 , " -ObtainAuthTokenFromServer- Failed to create AuthPolicy object, error = %08X \n " , retStatus ) ;
2006-11-13 06:20:43 +01:00
}
}
else
{
2007-01-12 09:43:53 +01:00
DbgTrace ( 0 , " -ObtainAuthTokenFromServer- Failed to create GetAuthPolicyResp object, error = %08X \n " , retStatus ) ;
2006-11-13 06:20:43 +01:00
}
}
else
{
2007-01-12 09:43:53 +01:00
DbgTrace ( 0 , " -ObtainAuthTokenFromServer- Did not receive GetAuthPolicy Response data \n " , 0 ) ;
2007-01-12 13:49:25 +01:00
retStatus = CasaStatusBuild ( CASA_SEVERITY_ERROR ,
CASA_FACILITY_AUTHTOKEN ,
CASA_STATUS_SERVER_ERROR ) ;
2006-11-13 06:20:43 +01:00
}
}
else
{
DbgTrace ( 0 , " -ObtainAuthTokenFromServer- GetAuthPolicy Rpc failure, error = %08X \n " , retStatus ) ;
}
// Free resources that may be hanging around
if ( pReqMsg )
2007-01-04 11:18:40 +01:00
{
// Clear the memory before freeing up the request message since it
// may contain security sensitive data.
memset ( pReqMsg , 0 , strlen ( pReqMsg ) ) ;
2006-11-13 06:20:43 +01:00
free ( pReqMsg ) ;
2007-01-04 11:18:40 +01:00
}
2006-11-13 06:20:43 +01:00
if ( pRespMsg )
2007-01-04 11:18:40 +01:00
{
// Clear the memory before freeing up the response message since it
// may contain security sensitive data.
2007-01-04 14:27:31 +01:00
memset ( pRespMsg , 0 , respLen ) ;
2006-11-13 06:20:43 +01:00
free ( pRespMsg ) ;
2007-01-04 11:18:40 +01:00
}
2006-11-13 06:20:43 +01:00
if ( pSessionToken )
2007-01-04 11:18:40 +01:00
{
// Clear the memory before freeing up the token since it is
// security sensitive data.
memset ( pSessionToken , 0 , strlen ( pSessionToken ) ) ;
2006-11-13 06:20:43 +01:00
free ( pSessionToken ) ;
2007-01-04 11:18:40 +01:00
}
2006-11-13 06:20:43 +01:00
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
ObtainAuthTokenInt (
IN const char * pServiceName ,
IN const char * pHostName ,
2007-04-03 00:16:07 +02:00
IN const void * pCredStoreScope ,
2006-11-13 06:20:43 +01:00
INOUT char * pAuthTokenBuf ,
2007-04-03 00:16:07 +02:00
INOUT int * pAuthTokenBufLen )
2006-11-13 06:20:43 +01:00
//
// Arguments:
// pServiceName -
// Pointer to NULL terminated string that contains the
// name of the service to which the client is trying to
// authenticate.
//
// pHostName -
// Pointer to NULL terminated string that contains the
// name of the host where resides the service to which the
// client is trying to authenticate. Note that the name
// can either be a DNS name or a dotted IP address.
//
2007-04-03 00:16:07 +02:00
// pCredStoreScope -
// Pointer to CASA structure for scoping credential store access
// to specific users. This can only be leveraged by applications
// running in the context of System.
//
2006-11-13 06:20:43 +01:00
// pAuthTokenBuf -
// Pointer to buffer that will receive the authentication
// token. The length of this buffer is specified by the
// pAuthTokenBufLen parameter. Note that the the authentication
// token will be in the form of a NULL terminated string.
//
// pAuthTokenBufLen -
// Pointer to integer that contains the length of the
// buffer pointed at by pAuthTokenBuf. 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 pAuthTokenBuf is
// not large enough.
2007-04-03 00:16:07 +02:00
//
2006-11-13 06:20:43 +01:00
// Returns:
// Casa Status
//
// Description:
// Get authentication token to authenticate user to specified
2006-11-18 13:33:14 +01:00
// service at host. The user is scoped using the info associated
// with the magic cookie.
2006-11-13 06:20:43 +01:00
//
// L2
//=======================================================================--
{
CasaStatus retStatus = CASA_STATUS_SUCCESS ;
AuthCacheEntry * pCacheEntry ;
char * pNormalizedHostName ;
char * pToken ;
HANDLE hUserMutex = NULL ;
DbgTrace ( 1 , " -ObtainAuthTokenInt- Start \n " , 0 ) ;
// Verify the input parameters
if ( pServiceName = = NULL
| | pHostName = = NULL
| | pAuthTokenBufLen = = NULL
| | ( * pAuthTokenBufLen ! = 0 & & pAuthTokenBuf = = NULL ) )
{
DbgTrace ( 0 , " -ObtainAuthTokenInt- Invalid parameter \n " , 0 ) ;
retStatus = CasaStatusBuild ( CASA_SEVERITY_ERROR ,
CASA_FACILITY_AUTHTOKEN ,
CASA_STATUS_INVALID_PARAMETER ) ;
goto exit ;
}
DbgTrace ( 1 , " -ObtainAuthTokenInt- ServiceName = %s \n " , pServiceName ) ;
DbgTrace ( 1 , " -ObtainAuthTokenInt- HostName = %s \n " , pHostName ) ;
DbgTrace ( 1 , " -ObtainAuthTokenInt- BufferLength = %d \n " , * pAuthTokenBufLen ) ;
// Obtain our synchronization mutex
AcquireModuleMutex ;
// Create user synchronization mutex
retStatus = CreateUserMutex ( & hUserMutex ) ;
if ( retStatus ! = CASA_STATUS_SUCCESS )
{
DbgTrace ( 0 , " -ObtainAuthTokenInt- Error creating mutex for the user \n " , 0 ) ;
goto exit ;
}
// Make sure we are fully initialized
if ( g_bInitialized = = false )
{
retStatus = InitializeLibrary ( ) ;
if ( retStatus = = CASA_STATUS_SUCCESS )
{
g_bInitialized = true ;
}
else
{
goto exit ;
}
}
// Release our synchronization mutex
ReleaseModuleMutex ;
// Normalize the host name
pNormalizedHostName = NormalizeHostName ( pHostName ) ;
if ( pNormalizedHostName )
{
// Start user process synchronization
AcquireUserMutex ( hUserMutex ) ;
// Try to find a cache entry for the service
pCacheEntry = FindAuthTokenEntryInCache ( pServiceName ,
pNormalizedHostName ,
pCredStoreScope ) ;
if ( pCacheEntry = = NULL )
{
// Initialize to retry in case of failure
2006-11-30 19:21:42 +01:00
int cacheEntryLifetime = DEFAULT_RETRY_LIFETIME ;
2007-04-03 00:16:07 +02:00
bool advisedToRetry ;
2006-11-13 06:20:43 +01:00
// Cache entry created, now try to obtain auth token from the CASA Server
2007-01-04 11:18:40 +01:00
pToken = NULL ;
2006-11-13 06:20:43 +01:00
retStatus = ObtainAuthTokenFromServer ( pServiceName ,
2007-03-05 07:48:26 +01:00
pHostName ,
2006-11-13 06:20:43 +01:00
pNormalizedHostName ,
2007-04-03 00:16:07 +02:00
pCredStoreScope ,
2006-11-13 06:20:43 +01:00
& pToken ,
& cacheEntryLifetime ,
2007-04-03 00:16:07 +02:00
& advisedToRetry ) ;
// Retry if not successful and if advised to do so
if ( ! CASA_SUCCESS ( retStatus )
& & advisedToRetry )
{
retStatus = ObtainAuthTokenFromServer ( pServiceName ,
pHostName ,
pNormalizedHostName ,
pCredStoreScope ,
& pToken ,
& cacheEntryLifetime ,
& advisedToRetry ) ;
}
2006-11-13 06:20:43 +01:00
// 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 = CreateAuthTokenCacheEntry ( pServiceName ,
pNormalizedHostName ,
retStatus ,
pToken ,
cacheEntryLifetime ,
pCredStoreScope ) ;
if ( pCacheEntry )
{
// Release the cache entry if the resulting status is not successful
if ( ! CASA_SUCCESS ( retStatus ) )
{
FreeAuthCacheEntry ( pCacheEntry ) ;
}
}
}
2007-01-04 11:18:40 +01:00
// Release authentication token if present
if ( pToken )
{
// Clear the memory before releasing the buffer since it contains
// security sensitive data.
memset ( pToken , 0 , strlen ( pToken ) ) ;
free ( pToken ) ;
}
2006-11-13 06:20:43 +01:00
}
else
{
// Cache entry found, update the return status with the information saved in it
// and release it if its status is not successful.
if ( ! CASA_SUCCESS ( retStatus = pCacheEntry - > status ) )
{
FreeAuthCacheEntry ( pCacheEntry ) ;
}
}
// Try to return auth token if we have one to return
if ( CASA_SUCCESS ( retStatus ) )
{
int tokenLen = ( int ) strlen ( pCacheEntry - > token ) + 1 ;
// We have an authentication token, try to return it to the caller
// after verifying that the supplied buffer is big enough.
if ( * pAuthTokenBufLen > = tokenLen )
{
// Return the auth token to the caller
DbgTrace ( 2 , " -ObtainAuthTokenInt- Copying the token into the callers buffer \n " , 0 ) ;
strcpy ( pAuthTokenBuf , pCacheEntry - > token ) ;
}
else
{
2006-12-08 06:45:03 +01:00
if ( * pAuthTokenBufLen ! = 0 )
{
DbgTrace ( 0 , " -ObtainAuthTokenInt- The supplied buffer is not large enough " , 0 ) ;
}
2006-11-13 06:20:43 +01:00
retStatus = CasaStatusBuild ( CASA_SEVERITY_ERROR ,
CASA_FACILITY_AUTHTOKEN ,
CASA_STATUS_BUFFER_OVERFLOW ) ;
}
// Return the token length to the caller
* pAuthTokenBufLen = tokenLen ;
FreeAuthCacheEntry ( pCacheEntry ) ;
}
// Stop user process synchronization
ReleaseUserMutex ( hUserMutex ) ;
// Free the space allocated for the normalized host name
free ( pNormalizedHostName ) ;
}
else
{
DbgTrace ( 0 , " -ObtainAuthTokenInt- Host name normalization failed \n " , 0 ) ;
retStatus = CasaStatusBuild ( CASA_SEVERITY_ERROR ,
CASA_FACILITY_AUTHTOKEN ,
2007-01-12 13:49:25 +01:00
CASA_STATUS_NAME_RESOLVE_ERROR ) ;
2006-11-13 06:20:43 +01:00
}
exit :
if ( hUserMutex ! = NULL )
{
DestroyUserMutex ( hUserMutex ) ;
}
DbgTrace ( 1 , " -ObtainAuthTokenInt- End, retStatus = %08X \n " , retStatus ) ;
return retStatus ;
}
//++=======================================================================
CasaStatus SSCS_CALL
ObtainAuthToken (
IN const char * pServiceName ,
IN const char * pHostName ,
INOUT char * pAuthTokenBuf ,
INOUT int * pAuthTokenBufLen )
//
// Arguments:
// pServiceName -
// Pointer to NULL terminated string that contains the
// name of the service to which the client is trying to
// authenticate.
//
// pHostName -
// Pointer to NULL terminated string that contains the
// name of the host where resides the service to which the
// client is trying to authenticate. Note that the name
// can either be a DNS name or a dotted IP address.
//
// pAuthTokenBuf -
// Pointer to buffer that will receive the authentication
// token. The length of this buffer is specified by the
// pAuthTokenBufLen parameter. Note that the the authentication
// token will be in the form of a NULL terminated string.
//
// pAuthTokenBufLen -
// Pointer to integer that contains the length of the
// buffer pointed at by pAuthTokenBuf. 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 pAuthTokenBuf is
// not large enough.
//
// Returns:
// Casa Status
//
// Description:
// Get authentication token to authenticate user to specified
// service at host.
//
// L2
//=======================================================================--
{
CasaStatus retStatus ;
DbgTrace ( 1 , " -ObtainAuthToken- Start \n " , 0 ) ;
// Call our internal worker
retStatus = ObtainAuthTokenInt ( pServiceName ,
pHostName ,
2007-04-03 00:16:07 +02:00
NULL ,
2006-11-13 06:20:43 +01:00
pAuthTokenBuf ,
2007-04-03 00:16:07 +02:00
pAuthTokenBufLen ) ;
2006-11-13 06:20:43 +01:00
DbgTrace ( 1 , " -ObtainAuthToken- End, retStatus = %08X \n " , retStatus ) ;
return retStatus ;
}
2007-04-13 21:21:40 +02:00
//++=======================================================================
void
CleanUpAuthTokenCacheInt (
IN const void * pCredStoreScope )
//
// Arguments:
// pCredStoreScope -
// Pointer to CASA structure for scoping credential store access
// to specific users. This can only be leveraged by applications
// running in the context of System.
//
// Returns:
// Nothing
//
// Description:
// Flush the AuthToken cache.
//=======================================================================--
{
CasaStatus retStatus ;
HANDLE hUserMutex = NULL ;
DbgTrace ( 1 , " -CleanUpAuthTokenCacheInt- Start \n " , 0 ) ;
// Obtain our synchronization mutex
AcquireModuleMutex ;
// Create user synchronization mutex
retStatus = CreateUserMutex ( & hUserMutex ) ;
if ( retStatus ! = CASA_STATUS_SUCCESS )
{
DbgTrace ( 0 , " -CleanUpAuthTokenCacheInt- Error creating mutex for the user \n " , 0 ) ;
goto exit ;
}
// Make sure we are fully initialized
if ( g_bInitialized = = false )
{
retStatus = InitializeLibrary ( ) ;
if ( retStatus = = CASA_STATUS_SUCCESS )
{
g_bInitialized = true ;
}
else
{
goto exit ;
}
}
// Release our synchronization mutex
ReleaseModuleMutex ;
// Start user process synchronization
AcquireUserMutex ( hUserMutex ) ;
// Delete all of the tokens in our cache
DeleteAuthTokenEntriesInCache ( pCredStoreScope ) ;
DeleteSessionTokenEntriesInCache ( pCredStoreScope ) ;
// Stop user process synchronization
ReleaseUserMutex ( hUserMutex ) ;
exit :
if ( hUserMutex ! = NULL )
{
DestroyUserMutex ( hUserMutex ) ;
}
DbgTrace ( 1 , " -CleanUpAuthTokenCacheInt- End \n " , 0 ) ;
}
//++=======================================================================
void SSCS_CALL
CleanUpAuthTokenCache ( void )
//
// Arguments: None.
//
// Returns:
// Nothing
//
// Description:
// Flush the AuthToken cache.
//=======================================================================--
{
DbgTrace ( 1 , " -CleanUpAuthTokenCache- Start \n " , 0 ) ;
// Call our internal worker
CleanUpAuthTokenCacheInt ( NULL ) ;
DbgTrace ( 1 , " -CleanUpAuthTokenCache- End \n " , 0 ) ;
}
2006-11-13 06:20:43 +01:00
//++=======================================================================
int
InitializeLibrary ( void )
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
int retStatus = - 1 ;
int getConfigStatus = - 1 ;
ConfigIf * pClientConfigIf ;
2006-11-18 13:33:14 +01:00
char * pDebugLevelSetting ;
2007-03-05 07:48:26 +01:00
char * pDebugLogFolderPathSetting ;
2006-11-13 06:20:43 +01:00
char * pATSPortSetting ;
2007-03-05 07:48:26 +01:00
char * pATSHostNameSetting ;
2006-11-13 06:20:43 +01:00
char * pDisableSecureConnections ;
char * pAllowInvalidCerts ;
char * pUsersCannotAllowInvalidCerts ;
DbgTrace ( 1 , " -InitializeLibrary- Start \n " , 0 ) ;
// Try to obtain client configuration settings
getConfigStatus = GetConfigInterface ( clientConfigFolder ,
" client " ,
& pClientConfigIf ) ;
if ( CASA_SUCCESS ( getConfigStatus )
& & CasaStatusCode ( getConfigStatus ) ! = CASA_STATUS_OBJECT_NOT_FOUND )
{
2006-11-18 13:33:14 +01:00
// Check if a DebugLevel has been configured
pDebugLevelSetting = pClientConfigIf - > getEntryValue ( pClientConfigIf , " DebugLevel " ) ;
if ( pDebugLevelSetting ! = NULL )
{
DbgTrace ( 0 , " -InitializeLibrary- DebugLevel configured = %s \n " , pDebugLevelSetting ) ;
// Convert the number to hex
DebugLevel = ( int ) dtoul ( pDebugLevelSetting , strlen ( pDebugLevelSetting ) ) ;
// Free the buffer holding the debug level
2007-03-05 07:48:26 +01:00
pClientConfigIf - > freeValueString ( pClientConfigIf , pDebugLevelSetting ) ;
}
// Check if a DebugLogFolderPath has been configured
pDebugLogFolderPathSetting = pClientConfigIf - > getEntryValue ( pClientConfigIf , " DebugLogFolderPath " ) ;
if ( pDebugLogFolderPathSetting ! = NULL )
{
DbgTrace ( 0 , " -InitializeLibrary- DebugLogFolderPath configured = %s \n " , pDebugLogFolderPathSetting ) ;
// Use the setting to come up with the path to the debug log file
g_pDebugLogFilePath = malloc ( strlen ( LOG_FILE_NAME ) + strlen ( pDebugLogFolderPathSetting ) + 1 ) ;
if ( g_pDebugLogFilePath )
{
strcpy ( g_pDebugLogFilePath , pDebugLogFolderPathSetting ) ;
strcat ( g_pDebugLogFilePath , LOG_FILE_NAME ) ;
}
else
{
DbgTrace ( 0 , " -InitializeLibrary- Failed to allocate buffer for debug file path \n " , 0 ) ;
}
// Free the buffer holding the debug folder path
pClientConfigIf - > freeValueString ( pClientConfigIf , pDebugLogFolderPathSetting ) ;
2006-11-18 13:33:14 +01:00
}
2006-11-13 06:20:43 +01:00
// Check if an ATS hostname has been configured
2007-03-05 07:48:26 +01:00
pATSHostNameSetting = pClientConfigIf - > getEntryValue ( pClientConfigIf , " ATS-hostname " ) ;
if ( pATSHostNameSetting ! = NULL )
2006-11-13 06:20:43 +01:00
{
2007-03-05 07:48:26 +01:00
DbgTrace ( 0 , " -InitializeLibrary- ATS hostname configured = %s \n " , pATSHostNameSetting ) ;
// Remember the ATS host name
g_pATSHostName = malloc ( strlen ( pATSHostNameSetting ) + 1 ) ;
if ( g_pATSHostName )
{
strcpy ( g_pATSHostName , pATSHostNameSetting ) ;
}
else
{
DbgTrace ( 0 , " -InitializeLibrary- Failed to allocate buffer for ATS host name \n " , 0 ) ;
}
// Free the buffer holding the ats host name setting
pClientConfigIf - > freeValueString ( pClientConfigIf , pATSHostNameSetting ) ;
2006-11-13 06:20:43 +01:00
}
// Check if the DisableSecureConnections setting has been configured
pDisableSecureConnections = pClientConfigIf - > getEntryValue ( pClientConfigIf , " DisableSecureConnections " ) ;
if ( pDisableSecureConnections ! = NULL )
{
DbgTrace ( 0 , " -InitializeLibrary- DisableSecureConnections setting configured = %s \n " , pDisableSecureConnections ) ;
// Adjust the g_rpcFlags variable based on the setting
2007-04-03 00:16:07 +02:00
if ( _stricmp ( pDisableSecureConnections , " true " ) = = 0 )
2006-11-13 06:20:43 +01:00
{
g_rpcFlags & = ~ SECURE_RPC_FLAG ;
}
2007-04-03 00:16:07 +02:00
else if ( _stricmp ( pDisableSecureConnections , " false " ) = = 0 )
2006-11-13 06:20:43 +01:00
{
g_rpcFlags | = SECURE_RPC_FLAG ;
}
// Free the buffer holding the DisableSecureConnections setting
2007-03-05 07:48:26 +01:00
pClientConfigIf - > freeValueString ( pClientConfigIf , pDisableSecureConnections ) ;
2006-11-13 06:20:43 +01:00
}
2007-03-05 07:48:26 +01:00
// Check the AllowUntrustedCerts setting if using secure connections
2006-11-13 06:20:43 +01:00
if ( g_rpcFlags & SECURE_RPC_FLAG )
{
2007-03-05 07:48:26 +01:00
// Check if the AllowUntrustedCerts setting has been configured
pAllowInvalidCerts = pClientConfigIf - > getEntryValue ( pClientConfigIf , " AllowUntrustedCerts " ) ;
2006-11-13 06:20:43 +01:00
if ( pAllowInvalidCerts ! = NULL )
{
2007-03-05 07:48:26 +01:00
DbgTrace ( 0 , " -InitializeLibrary- AllowUntrustedCerts setting configured = %s \n " , pAllowInvalidCerts ) ;
2006-11-13 06:20:43 +01:00
// Adjust the g_rpcFlags variable based on the setting
if ( stricmp ( pAllowInvalidCerts , " false " ) = = 0 )
{
g_rpcFlags & = ~ ALLOW_INVALID_CERTS_RPC_FLAG ;
}
else if ( stricmp ( pAllowInvalidCerts , " true " ) = = 0 )
{
g_rpcFlags | = ALLOW_INVALID_CERTS_RPC_FLAG ;
}
// Free the buffer holding the AllowInvalidCerts setting
2007-03-05 07:48:26 +01:00
pClientConfigIf - > freeValueString ( pClientConfigIf , pAllowInvalidCerts ) ;
2006-11-13 06:20:43 +01:00
}
// Check the UsersCannotAllowInvalidCerts setting if not allowing invalid certs.
if ( ( g_rpcFlags & ALLOW_INVALID_CERTS_RPC_FLAG ) = = 0 )
{
// Check if the UsersCannotAllowInvalidCerts setting has been configured
pUsersCannotAllowInvalidCerts = pClientConfigIf - > getEntryValue ( pClientConfigIf , " UsersCannotAllowInvalidCerts " ) ;
if ( pUsersCannotAllowInvalidCerts ! = NULL )
{
DbgTrace ( 0 , " -InitializeLibrary- UsersCannotAllowInvalidCerts setting configured = %s \n " , pUsersCannotAllowInvalidCerts ) ;
// Adjust the g_rpcFlags variable based on the setting
if ( stricmp ( pUsersCannotAllowInvalidCerts , " false " ) = = 0 )
{
g_rpcFlags | = ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG ;
}
else if ( stricmp ( pUsersCannotAllowInvalidCerts , " true " ) = = 0 )
{
g_rpcFlags & = ~ ALLOW_INVALID_CERTS_USER_APPROVAL_RPC_FLAG ;
}
// Free the buffer holding the UsersCannotAllowInvalidCerts setting
2007-03-05 07:48:26 +01:00
pClientConfigIf - > freeValueString ( pClientConfigIf , pUsersCannotAllowInvalidCerts ) ;
2006-11-13 06:20:43 +01:00
}
}
}
// Check if an ATS port number has been configured
pATSPortSetting = pClientConfigIf - > getEntryValue ( pClientConfigIf , " ATS-port " ) ;
if ( pATSPortSetting ! = NULL )
{
DbgTrace ( 0 , " -InitializeLibrary- ATS port number configured = %s \n " , pATSPortSetting ) ;
// Convert the number to hex
g_ATSPort = ( int ) dtoul ( pATSPortSetting , strlen ( pATSPortSetting ) ) ;
// Free the buffer holding the port number
2007-03-05 07:48:26 +01:00
pClientConfigIf - > freeValueString ( pClientConfigIf , pATSPortSetting ) ;
2006-11-13 06:20:43 +01:00
}
// Release config interface instance
pClientConfigIf - > releaseReference ( pClientConfigIf ) ;
}
// Initialize the host name normalization
retStatus = InitializeHostNameNormalization ( ) ;
if ( CASA_SUCCESS ( retStatus ) )
{
// Normalize ATS host name if configured
if ( g_pATSHostName )
{
char * pNormalizedHostName = NormalizeHostName ( g_pATSHostName ) ;
if ( pNormalizedHostName )
{
// Use this name instead of the one that we already have
free ( g_pATSHostName ) ;
g_pATSHostName = pNormalizedHostName ;
}
else
{
DbgTrace ( 0 , " -InitializeLibrary- ATS Hostname normalization failed \n " , 0 ) ;
}
}
// Initialize the auth cache
retStatus = InitializeAuthCache ( ) ;
if ( CASA_SUCCESS ( retStatus ) )
{
retStatus = InitializeRpc ( ) ;
}
else
{
DbgTrace ( 0 , " -InitializeLibrary- Auth cache intialization failed \n " , 0 ) ;
}
}
else
{
DbgTrace ( 0 , " -InitializeLibrary- HostName Normalizer intialization failed \n " , 0 ) ;
}
DbgTrace ( 1 , " -InitializeLibrary- End, retStatus = %08X \n " , retStatus ) ;
return retStatus ;
}
2007-01-29 11:46:18 +01:00
//++=======================================================================
void
UnInitializeLibrary ( void )
//
// Arguments:
//
// Returns:
//
// Abstract:
//
// Notes:
//
// L2
//=======================================================================--
{
DbgTrace ( 1 , " -UnInitializeLibrary- Start \n " , 0 ) ;
// Un-initialize the host name normalization
UnInitializeHostNameNormalization ( ) ;
// Un-initialize the auth cache
UnInitializeAuthCache ( ) ;
// Un-initialize the Rpc engine
UnInitializeRpc ( ) ;
2007-03-05 07:48:26 +01:00
// Free necessary buffers
if ( g_pDebugLogFilePath )
2007-03-05 19:01:32 +01:00
{
char * pBuffer = g_pDebugLogFilePath ;
g_pDebugLogFilePath = NULL ;
free ( pBuffer ) ;
}
2007-03-05 07:48:26 +01:00
if ( g_pATSHostName )
free ( g_pATSHostName ) ;
2007-01-29 11:46:18 +01:00
DbgTrace ( 1 , " -UnInitializeLibrary- End \n " , 0 ) ;
}
2006-11-13 06:20:43 +01:00
//++=======================================================================
//++=======================================================================
//++=======================================================================