2c8668479c
to be able to deliver the client component onto distributions targeting desktops without having to deliver the server components. This commit is for the resulting client project.
344 lines
13 KiB
C
344 lines
13 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"
|
|
|
|
//===[ Type definitions ]==================================================
|
|
|
|
//
|
|
// AuthMechMod definition
|
|
//
|
|
typedef struct _AuthMechMod
|
|
{
|
|
LIST_ENTRY listEntry;
|
|
char *pAuthTypeName;
|
|
int authTypeNameLen;
|
|
LIB_HANDLE libHandle;
|
|
AuthTokenIf *pAuthTokenIf;
|
|
|
|
} AuthMechMod, *PAuthMechMod;
|
|
|
|
|
|
//===[ Function prototypes ]===============================================
|
|
|
|
//===[ Global variables ]==================================================
|
|
|
|
// AuthMechModule List and syncronizing mutex
|
|
static
|
|
LIST_ENTRY g_authMechModuleListHead = {&g_authMechModuleListHead,
|
|
&g_authMechModuleListHead};
|
|
|
|
|
|
//++=======================================================================
|
|
static
|
|
CasaStatus
|
|
GetAuthTokenIf(
|
|
IN const char *pAuthTypeName,
|
|
INOUT AuthTokenIf **ppAuthTokenIf)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// Environment:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus;
|
|
ConfigIf *pModuleConfigIf;
|
|
|
|
DbgTrace(2, "-GetAuthTokenIf- Start\n", 0);
|
|
|
|
// Get the configuration for the module
|
|
retStatus = GetConfigInterface(mechConfigFolder,
|
|
pAuthTypeName,
|
|
&pModuleConfigIf);
|
|
if (CASA_SUCCESS(retStatus)
|
|
&& CasaStatusCode(retStatus) != CASA_STATUS_OBJECT_NOT_FOUND)
|
|
{
|
|
LIST_ENTRY *pListEntry;
|
|
AuthMechMod *pAuthMechMod = NULL;
|
|
int authTypeNameLen = strlen(pAuthTypeName);
|
|
|
|
// Look if we already have the module in our list
|
|
pListEntry = g_authMechModuleListHead.Flink;
|
|
while (pListEntry != &g_authMechModuleListHead)
|
|
{
|
|
// Get pointer to the current entry
|
|
pAuthMechMod = CONTAINING_RECORD(pListEntry, AuthMechMod, listEntry);
|
|
|
|
// Check if this is the module that we need
|
|
if (pAuthMechMod->authTypeNameLen == authTypeNameLen
|
|
&& memcmp(pAuthTypeName, pAuthMechMod->pAuthTypeName, authTypeNameLen) == 0)
|
|
{
|
|
// This is the module that we need, stop looking.
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// This is not the module that we are looking for
|
|
pAuthMechMod = NULL;
|
|
}
|
|
|
|
// Advance to the next entry
|
|
pListEntry = pListEntry->Flink;
|
|
}
|
|
|
|
// Proceed based on whether or not a module was found
|
|
if (pAuthMechMod)
|
|
{
|
|
// Module found in our list, provide the caller with its AuthTokenIf
|
|
// instance after we have incremented its reference count.
|
|
pAuthMechMod->pAuthTokenIf->addReference(pAuthMechMod->pAuthTokenIf);
|
|
*ppAuthTokenIf = pAuthMechMod->pAuthTokenIf;
|
|
|
|
// Success
|
|
retStatus = CASA_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
// Needed module not found in our list, create an entry.
|
|
pAuthMechMod = (AuthMechMod*) malloc(sizeof(*pAuthMechMod));
|
|
if (pAuthMechMod)
|
|
{
|
|
// Allocate buffer to contain the authentication type name within the module entry
|
|
pAuthMechMod->pAuthTypeName = (char*) malloc(authTypeNameLen + 1);
|
|
if (pAuthMechMod->pAuthTypeName)
|
|
{
|
|
char *pLibraryName;
|
|
|
|
// Initialize the library handle field
|
|
pAuthMechMod->libHandle = NULL;
|
|
|
|
// Save the auth type name within the entry
|
|
strcpy(pAuthMechMod->pAuthTypeName, pAuthTypeName);
|
|
pAuthMechMod->authTypeNameLen = authTypeNameLen;
|
|
|
|
// Obtain the name of the library that we must load
|
|
pLibraryName = pModuleConfigIf->getEntryValue(pModuleConfigIf, "LibraryName");
|
|
if (pLibraryName)
|
|
{
|
|
// Load the library
|
|
pAuthMechMod->libHandle = OpenLibrary(pLibraryName);
|
|
if (pAuthMechMod->libHandle)
|
|
{
|
|
PFN_GetAuthTokenIfRtn pGetAuthTokenIfRtn;
|
|
|
|
// Library has been loaded, now get a pointer to its GetAuthTokenInterface routine
|
|
pGetAuthTokenIfRtn = (PFN_GetAuthTokenIfRtn) GetFunctionPtr(pAuthMechMod->libHandle,
|
|
GET_AUTH_TOKEN_INTERFACE_RTN_SYMBOL);
|
|
if (pGetAuthTokenIfRtn)
|
|
{
|
|
// Now, obtain the modules AuthTokenIf.
|
|
retStatus = (pGetAuthTokenIfRtn)(pModuleConfigIf, &pAuthMechMod->pAuthTokenIf);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-GetAuthTokenIf- GetFunctionPtr\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_LIBRARY_LOAD_FAILURE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-GetAuthTokenIf- OpenLibrary error\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_UNSUCCESSFUL);
|
|
}
|
|
|
|
// Free the buffer holding the library name
|
|
free(pLibraryName);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-GetAuthTokenIf- Library name not configured\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_CONFIGURATION_ERROR);
|
|
}
|
|
|
|
// Check if we were successful at obtaining the AuthTokenIf instance for the
|
|
// module.
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
// Insert the entry in the list, provide the caller with its AuthTokenIf
|
|
// instance after we have incremented its reference count.
|
|
InsertTailList(&g_authMechModuleListHead, &pAuthMechMod->listEntry);
|
|
pAuthMechMod->pAuthTokenIf->addReference(pAuthMechMod->pAuthTokenIf);
|
|
*ppAuthTokenIf = pAuthMechMod->pAuthTokenIf;
|
|
}
|
|
else
|
|
{
|
|
// Failed, free resources.
|
|
free(pAuthMechMod->pAuthTypeName);
|
|
if (pAuthMechMod->libHandle)
|
|
CloseLibrary(pAuthMechMod->libHandle);
|
|
free(pAuthMechMod);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "GetAuthTokenIf-GetAuthTokenIf- Unable to allocate buffer\n", 0);
|
|
|
|
// Free buffer allocated for entry
|
|
free(pAuthMechMod);
|
|
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-GetAuthTokenIf- Unable to allocate buffer\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
}
|
|
|
|
// Release config interface instance
|
|
pModuleConfigIf->releaseReference(pModuleConfigIf);
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-GetAuthTokenIf- Unable to obtain config interface\n", 0);
|
|
retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_CONFIGURATION_ERROR);
|
|
}
|
|
|
|
DbgTrace(2, "-GetAuthTokenIf- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
CasaStatus
|
|
GetAuthMechToken(
|
|
IN AuthContext *pAuthContext,
|
|
IN const char *pHostName,
|
|
IN void *pCredStoreScope,
|
|
INOUT char **ppAuthToken)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Notes:
|
|
//
|
|
// L2
|
|
//=======================================================================--
|
|
{
|
|
CasaStatus retStatus = CasaStatusBuild(CASA_SEVERITY_ERROR,
|
|
CASA_FACILITY_AUTHTOKEN,
|
|
CASA_STATUS_UNSUCCESSFUL);
|
|
AuthTokenIf *pAuthTokenIf = NULL;
|
|
|
|
DbgTrace(1, "-GetAuthMechToken- Start\n", 0);
|
|
|
|
// Initialize output parameter
|
|
*ppAuthToken = NULL;
|
|
|
|
// Obtain the appropriate token interface for the authentication type
|
|
retStatus = GetAuthTokenIf(pAuthContext->pMechanism,
|
|
&pAuthTokenIf);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
char *pAuthToken = NULL;
|
|
int authTokenBufLen = 0;
|
|
|
|
// We found a provider for the service, query it for the buffer size
|
|
// needed to obtain the authentication token.
|
|
retStatus = pAuthTokenIf->getAuthToken(pAuthTokenIf,
|
|
pAuthContext->pContext,
|
|
pAuthContext->pMechInfo,
|
|
pHostName,
|
|
pCredStoreScope,
|
|
pAuthToken,
|
|
&authTokenBufLen);
|
|
if (CasaStatusCode(retStatus) == CASA_STATUS_BUFFER_OVERFLOW)
|
|
{
|
|
// Allocate buffer to hold the authentication token
|
|
pAuthToken = (char*) malloc(authTokenBufLen);
|
|
if (pAuthToken)
|
|
{
|
|
// Request the token from the provider
|
|
retStatus = pAuthTokenIf->getAuthToken(pAuthTokenIf,
|
|
pAuthContext->pContext,
|
|
pAuthContext->pMechInfo,
|
|
pHostName,
|
|
pCredStoreScope,
|
|
pAuthToken,
|
|
&authTokenBufLen);
|
|
if (CASA_SUCCESS(retStatus))
|
|
{
|
|
// Return the buffer containing the token to the caller
|
|
*ppAuthToken = pAuthToken;
|
|
}
|
|
else
|
|
{
|
|
// Free the allocated buffer
|
|
free(pAuthToken);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgTrace(0, "-GetAuthMechToken- Buffer allocation failure\n", 0);
|
|
}
|
|
}
|
|
|
|
// Release token interface
|
|
pAuthTokenIf->releaseReference(pAuthTokenIf);
|
|
}
|
|
else
|
|
{
|
|
// No authentication token interface available for authentication type
|
|
DbgTrace(0, "-GetAuthMechToken- Failed to obtain auth mech token interface\n", 0);
|
|
}
|
|
|
|
DbgTrace(1, "-GetAuthMechToken- End, retStatus = %08X\n", retStatus);
|
|
|
|
return retStatus;
|
|
}
|
|
|
|
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
//++=======================================================================
|
|
|