|
|
/*#----------------------------------------------------------------------------
** ** 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); }
|