You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
514 lines
15 KiB
514 lines
15 KiB
/*#----------------------------------------------------------------------------
|
|
**
|
|
** File: sspspm.c
|
|
**
|
|
** Synopsis: Security Protocol Module for SSPI Authentication providers.
|
|
**
|
|
** This module contains major funtions of the SEC_SSPI.DLL which
|
|
** allows the Internet Explorer to use SSPI providers for authentication.
|
|
** The function exported to the Internet Explorer is Ssp_Load() which
|
|
** passes the address of the Ssp__DownCall() function to the Explorer.
|
|
** Then the Explorer will call Ssp__DownCall() when it needs service from
|
|
** this SPM DLL. The two major functions called by Ssp__DownCall() to
|
|
** service Explorer's request are Ssp__PreProcessRequest() and
|
|
** Ssp__ProcessResponse(). In brief, Ssp__PreProcessRequest() is
|
|
** called before the Explorer sends out a request which does not have
|
|
** any 'Authorization' header yet. And Ssp__ProcessResponse() is called
|
|
** whenever the Explorer receives an 401 'Unauthorized' response from the
|
|
** server. This SPM DLL supports all SSPI packages which are installed
|
|
** on the machine. However, MSN will be given higher priority over the
|
|
** other SSPI packages if the user already logon to MSN; in that case,
|
|
** Ssp__PreProcessRequest() will always attach MSN authentication header
|
|
** to the out-going request.
|
|
**
|
|
** This SPM DLL is called by the Internet Explorer only for its
|
|
** The Internet Explorer only calls this SPM DLL when it needs
|
|
** authentication data in its request/response. In other words, the
|
|
** Explorer never calls this SPM DLL when an authentication succeeded;
|
|
** it never calls this DLL when it decide to give up on a connection
|
|
** because of server response timeout. Because of this fact, this SPM
|
|
** DLL never has sufficient information on the state of each server
|
|
** connection; it only know its state based on the content of the last
|
|
** request and the content of the current response. For this reason, this
|
|
** SPM DLL does not keep state information for each host it has visited
|
|
** unless the information is essential.
|
|
** The security context handle returned from the first call of
|
|
** InitializeSecurityContext() for NEGOTIATE message generation is
|
|
** always the identical for a SSPI package when the same server host is
|
|
** passed. Since the server host name is always in the request/response
|
|
** header, the only information essential in generating a NEGOTIATE or
|
|
** RESPONSE is already available in the header. So unlike most SSPI
|
|
** application, this DLL will not keep the security context handle which
|
|
** it received from the SSPI function calls. Whenever it needs to call
|
|
** the SSPI function for generating a RESPONSE, it will first call the
|
|
** SSPI function without the CHALLENGE to get a security context handle.
|
|
** Then it calls the SSPI function again with the CHALLENGE to generate
|
|
** a RESPONSE.
|
|
**
|
|
**
|
|
** Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
|
|
**
|
|
** Authors: LucyC Created 25 Sept. 1995
|
|
**
|
|
**---------------------------------------------------------------------------*/
|
|
#include "msnspmh.h"
|
|
#include <ntverp.h>
|
|
//
|
|
// Global variable where all the SSPI Pkgs data is collected
|
|
//
|
|
SspData *g_pSspData;
|
|
HINSTANCE g_hSecLib;
|
|
BOOL g_fIsWhistler = FALSE;
|
|
BOOL g_fCanUseCredMgr = FALSE;
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
**
|
|
** Function: SpmAddSSPIPkg
|
|
**
|
|
** Synopsis: This function adds a SSPI package to the SPM's package list.
|
|
**
|
|
** Arguments: pData - Points to the private SPM data structure containing
|
|
** the package list and the package info.
|
|
** pPkgName - package name
|
|
** cbMaxToken - max size of security token
|
|
**
|
|
** Returns: The index in the package list where this new package is added.
|
|
** If failed to add the new package, SSPPKG_ERROR is returned.
|
|
**
|
|
** History: LucyC Created 21 Oct. 1995
|
|
**
|
|
**---------------------------------------------------------------------------*/
|
|
UCHAR
|
|
SpmAddSSPIPkg (
|
|
SspData *pData,
|
|
LPTSTR pPkgName,
|
|
ULONG cbMaxToken
|
|
)
|
|
{
|
|
if ( !(pData->PkgList[pData->PkgCnt] =
|
|
LocalAlloc(0, sizeof(SSPAuthPkg))))
|
|
{
|
|
return SSPPKG_ERROR;
|
|
}
|
|
|
|
if ( !(pData->PkgList[pData->PkgCnt]->pName =
|
|
LocalAlloc(0, lstrlen(pPkgName)+1)))
|
|
{
|
|
LocalFree(pData->PkgList[pData->PkgCnt]);
|
|
pData->PkgList[pData->PkgCnt] = NULL;
|
|
return SSPPKG_ERROR;
|
|
}
|
|
|
|
lstrcpy (pData->PkgList[pData->PkgCnt]->pName, pPkgName);
|
|
pData->PkgList[ pData->PkgCnt ]->Capabilities = 0 ;
|
|
|
|
pData->PkgList[ pData->PkgCnt ]->cbMaxToken = cbMaxToken;
|
|
|
|
//
|
|
// Determine if this package supports anything of interest to
|
|
// us.
|
|
//
|
|
|
|
if ( lstrcmpi( pPkgName, NTLMSP_NAME_A ) == 0 )
|
|
{
|
|
//
|
|
// NTLM supports the standard credential structure
|
|
//
|
|
|
|
pData->PkgList[ pData->PkgCnt ]->Capabilities |= SSPAUTHPKG_SUPPORT_NTLM_CREDS ;
|
|
}
|
|
else if ( lstrcmpi( pPkgName, "Negotiate" ) == 0 )
|
|
{
|
|
//
|
|
// Negotiate supports that cred structure too
|
|
//
|
|
|
|
pData->PkgList[ pData->PkgCnt ]->Capabilities |= SSPAUTHPKG_SUPPORT_NTLM_CREDS ;
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Add more comparisons here, eventually.
|
|
//
|
|
|
|
;
|
|
}
|
|
|
|
pData->PkgCnt++;
|
|
return (pData->PkgCnt - 1);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
**
|
|
** Function: SpmFreePkgList
|
|
**
|
|
** Synopsis: This function frees memory allocated for the package list.
|
|
**
|
|
** Arguments: pData - Points to the private SPM data structure containing
|
|
** the package list and the package info.
|
|
**
|
|
** Returns: void.
|
|
**
|
|
** History: LucyC Created 21 Oct. 1995
|
|
**
|
|
**---------------------------------------------------------------------------*/
|
|
VOID
|
|
SpmFreePkgList (
|
|
SspData *pData
|
|
)
|
|
{
|
|
int ii;
|
|
|
|
for (ii = 0; ii < pData->PkgCnt; ii++)
|
|
{
|
|
LocalFree(pData->PkgList[ii]->pName);
|
|
|
|
LocalFree(pData->PkgList[ii]);
|
|
}
|
|
|
|
LocalFree(pData->PkgList);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
**
|
|
** Function: Ssp__Unload
|
|
**
|
|
** Synopsis: This function is called by the Internet Explorer before
|
|
** the SPM DLL is unloaded from the memory.
|
|
**
|
|
** Arguments: fpUI - From Explorer for making all UI_SERVICE call
|
|
** pvOpaqueOS - From Explorer for making all UI_SERVICE call
|
|
** htspm - the SPM structure which contains the global data
|
|
** storage for this SPM DLL.
|
|
**
|
|
** Returns: always returns SPM_STATUS_OK, which means successful.
|
|
**
|
|
** History: LucyC Created 25 Sept. 1995
|
|
**
|
|
**---------------------------------------------------------------------------*/
|
|
DWORD SSPI_Unload()
|
|
{
|
|
if (g_pSspData != NULL)
|
|
{
|
|
SpmFreePkgList(g_pSspData);
|
|
LocalFree(g_pSspData);
|
|
g_pSspData = NULL;
|
|
}
|
|
|
|
if (g_hSecLib)
|
|
{
|
|
FreeLibrary (g_hSecLib);
|
|
g_hSecLib = NULL;
|
|
}
|
|
|
|
return SPM_STATUS_OK;
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
**
|
|
** Function: SspSPM_InitData
|
|
**
|
|
** Synopsis: This function allocates and initializes global data structure
|
|
** of the SPM DLL.
|
|
**
|
|
** Arguments:
|
|
**
|
|
** Returns: Pointer to the allocated global data structure.
|
|
**
|
|
** History: LucyC Created 25 Sept. 1995
|
|
**
|
|
**---------------------------------------------------------------------------*/
|
|
LPVOID SSPI_InitGlobals(void)
|
|
{
|
|
SspData *pData = NULL;
|
|
OSVERSIONINFO VerInfo;
|
|
UCHAR lpszDLL[SSP_SPM_DLL_NAME_SIZE];
|
|
INIT_SECURITY_INTERFACE addrProcISI = NULL;
|
|
|
|
SECURITY_STATUS sstat;
|
|
ULONG ii, cntPkg;
|
|
PSecPkgInfo pPkgInfo = NULL;
|
|
PSecurityFunctionTable pFuncTbl = NULL;
|
|
|
|
if (g_pSspData)
|
|
return g_pSspData;
|
|
|
|
//
|
|
// Setup registry to enable MSN authentication package
|
|
// MSNSetupSspiReg();
|
|
//
|
|
|
|
//
|
|
// Initialize SSP SPM Global Data
|
|
//
|
|
|
|
//
|
|
// Find out which security DLL to use, depending on
|
|
// whether we are on NT or Win95
|
|
//
|
|
VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
|
|
if (!GetVersionEx (&VerInfo)) // If this fails, something has gone wrong
|
|
{
|
|
return (NULL);
|
|
}
|
|
|
|
if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
|
|
{
|
|
lstrcpy (lpszDLL, SSP_SPM_NT_DLL);
|
|
|
|
if ((VerInfo.dwMajorVersion >= 5) &&
|
|
(VerInfo.dwMinorVersion >= 1))
|
|
{
|
|
DWORD dwMaximumPersist = 0;
|
|
|
|
g_fIsWhistler = TRUE;
|
|
}
|
|
else
|
|
{
|
|
g_fIsWhistler = FALSE;
|
|
}
|
|
}
|
|
else if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
|
|
{
|
|
lstrcpy (lpszDLL, SSP_SPM_WIN95_DLL);
|
|
}
|
|
else if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_UNIX)
|
|
{
|
|
lstrcpy (lpszDLL, SSP_SPM_UNIX_DLL);
|
|
}
|
|
else
|
|
{
|
|
return (NULL);
|
|
}
|
|
|
|
if (!(pData = (SspData *) LocalAlloc(0, sizeof(SspData)))) {
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
//
|
|
// Keep these information in global SPM
|
|
//
|
|
ZeroMemory (pData, sizeof(SspData));
|
|
pData->MsnPkg = SSPPKG_NO_PKG;
|
|
|
|
//
|
|
// Load Security DLL
|
|
//
|
|
g_hSecLib = LoadLibrary (lpszDLL);
|
|
if (g_hSecLib == NULL)
|
|
{
|
|
// This should never happen.
|
|
goto Cleanup;
|
|
}
|
|
|
|
#ifdef UNIX
|
|
|
|
// A hack to undo the mistake in the sspi.h file. The change should be made
|
|
// to sspi.h
|
|
|
|
#if !defined(_UNICODE)
|
|
#undef SECURITY_ENTRYPOINT_ANSI
|
|
#define SECURITY_ENTRYPOINT_ANSI "InitSecurityInterfaceA"
|
|
#endif
|
|
|
|
addrProcISI = (INIT_SECURITY_INTERFACE) GetProcAddress( g_hSecLib,
|
|
SECURITY_ENTRYPOINT_ANSI);
|
|
#else
|
|
addrProcISI = (INIT_SECURITY_INTERFACE) GetProcAddress( g_hSecLib,
|
|
SECURITY_ENTRYPOINT);
|
|
#endif /* UNIX */
|
|
if (addrProcISI == NULL)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Get the SSPI function table
|
|
//
|
|
pFuncTbl = (*addrProcISI)();
|
|
|
|
//
|
|
// If we already loaded MSNSSPC.DLL explicitly, PkgCnt will not be zero;
|
|
// in that case, we only support MSN SSPI and do not need to call
|
|
// EnumerateSecurityPackages.
|
|
//
|
|
// So if we did not load MSNSSPC.DLL (i.e. PkgCnt is zero), we need to
|
|
// get the list of SSPI packages which we support from
|
|
// EnumerateSecurityPackages.
|
|
//
|
|
if (pData->PkgCnt == 0)
|
|
{
|
|
//
|
|
// Get list of packages supported
|
|
//
|
|
sstat = (*(pFuncTbl->EnumerateSecurityPackages))(&cntPkg, &pPkgInfo);
|
|
if (sstat != SEC_E_OK || pPkgInfo == NULL)
|
|
{
|
|
//
|
|
// ??? Should we give up here ???
|
|
// EnumerateSecurityPackage() failed
|
|
//
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (cntPkg)
|
|
{
|
|
//
|
|
// Create the package list
|
|
//
|
|
if (!(pData->PkgList = (PSSPAuthPkg *)LocalAlloc(0,
|
|
cntPkg*sizeof(PSSPAuthPkg))))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
|
|
for (ii = 0; ii < cntPkg; ii++)
|
|
{
|
|
if (lstrcmp (pPkgInfo[ii].Name, MSNSP_NAME) == 0)
|
|
{
|
|
//DebugTrace(SSPSPMID, "Found MSN SSPI package\n");
|
|
pData->MsnPkg = SpmAddSSPIPkg (
|
|
pData,
|
|
MSNSP_NAME,
|
|
MAX_AUTH_MSG_SIZE // 11000 hard-coded
|
|
);
|
|
if (pData->MsnPkg == SSPPKG_ERROR)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//DebugTrace(SSPSPMID, "Found %s SSPI package\n",
|
|
// pPkgInfo[ii].Name);
|
|
|
|
if (SpmAddSSPIPkg (pData,
|
|
pPkgInfo[ii].Name,
|
|
pPkgInfo[ii].cbMaxToken
|
|
) == SSPPKG_ERROR)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pData->pFuncTbl = pFuncTbl;
|
|
pData->bKeepList = TRUE; // By default, keep a list of non-MSN servers
|
|
|
|
if (pData->PkgCnt == 0)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
g_pSspData = pData;
|
|
pData = NULL;
|
|
|
|
Cleanup:
|
|
|
|
|
|
if( pPkgInfo != NULL )
|
|
{
|
|
//
|
|
// Free buffer returned by the enumerate security package function
|
|
//
|
|
|
|
(*(pFuncTbl->FreeContextBuffer))(pPkgInfo);
|
|
}
|
|
|
|
if( pData != NULL )
|
|
{
|
|
SpmFreePkgList (pData);
|
|
}
|
|
|
|
return (g_pSspData);
|
|
}
|
|
|
|
INT
|
|
GetPkgId(LPTSTR lpszPkgName)
|
|
{
|
|
|
|
int ii;
|
|
|
|
if ( g_pSspData == NULL )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
for (ii = 0; ii < g_pSspData->PkgCnt; ii++)
|
|
{
|
|
#ifdef UNIX
|
|
if (!lstrcmpi(g_pSspData->PkgList[ii]->pName, lpszPkgName))
|
|
#else
|
|
if (!lstrcmp(g_pSspData->PkgList[ii]->pName, lpszPkgName))
|
|
#endif /* UNIX */
|
|
{
|
|
return(ii);
|
|
}
|
|
}
|
|
|
|
return(-1);
|
|
}
|
|
|
|
DWORD
|
|
GetPkgCapabilities(
|
|
INT Package
|
|
)
|
|
{
|
|
if ( Package < g_pSspData->PkgCnt )
|
|
{
|
|
return g_pSspData->PkgList[ Package ]->Capabilities ;
|
|
}
|
|
else
|
|
return 0 ;
|
|
}
|
|
|
|
ULONG
|
|
GetPkgMaxToken(
|
|
INT Package
|
|
)
|
|
{
|
|
if ( Package < g_pSspData->PkgCnt )
|
|
{
|
|
return g_pSspData->PkgList[ Package ]->cbMaxToken;
|
|
}
|
|
else {
|
|
// be compatible with old static buffer size
|
|
return MAX_AUTH_MSG_SIZE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Calls to this function are serialized
|
|
//
|
|
|
|
DWORD_PTR SSPI_InitScheme (LPCSTR lpszScheme)
|
|
{
|
|
int ii;
|
|
|
|
if (!SSPI_InitGlobals())
|
|
return 0;
|
|
|
|
// Once initialized, check to see if this scheme is installed
|
|
for (ii = 0; ii < g_pSspData->PkgCnt &&
|
|
#ifdef UNIX
|
|
lstrcmpi (g_pSspData->PkgList[ii]->pName, lpszScheme); ii++);
|
|
#else
|
|
lstrcmp (g_pSspData->PkgList[ii]->pName, lpszScheme); ii++);
|
|
#endif /* UNIX */
|
|
|
|
if (ii >= g_pSspData->PkgCnt)
|
|
{
|
|
// This scheme is not installed on this machine
|
|
return (0);
|
|
}
|
|
|
|
return ((DWORD_PTR)g_pSspData);
|
|
}
|