Leaked source code of windows server 2003
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.
 
 
 
 
 
 

615 lines
14 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows NT
//
// Copyright (C) Microsoft Corporation, 1995 - 1998
//
// File: ceppswrd.cpp
//
// Contents: Cisco enrollment protocol implementation. This module
// implement the password hash table.
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include <dbgdef.h>
DWORD g_dwPasswordCount=0;
DWORD g_dwMaxPassword=0;
DWORD g_dwPasswordValidity=0;
CEP_PASSWORD_TABLE_INFO g_CEPPasswordTable;
//***************************************************************************
//
// The following are APIs called internally.
//
//
//***************************************************************************
//--------------------------------------------------------------------------
//
// CEPPasswordFreePasswordEntry
//
//--------------------------------------------------------------------------
void CEPPasswordFreePasswordEntry(CEP_PASSWORD_ENTRY *pPasswordEntry)
{
if(pPasswordEntry)
{
if(pPasswordEntry->pwszPassword)
free(pPasswordEntry->pwszPassword);
free(pPasswordEntry);
}
}
//--------------------------------------------------------------------------
//
// CEPPasswordFreeValidityEntry
//
//--------------------------------------------------------------------------
void CEPPasswordFreeValidityEntry(CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry,
BOOL fFreePasswordEntry)
{
if(pValidityEntry)
{
if(fFreePasswordEntry)
CEPPasswordFreePasswordEntry(pValidityEntry->pPasswordEntry);
free(pValidityEntry);
}
}
//--------------------------------------------------------------------------
//
// CEPHashPassword
//
// For any cases that we can not convert the psz, we use index 0.
//--------------------------------------------------------------------------
BOOL CEPHashPassword(LPWSTR pwsz, DWORD *pdw)
{
WCHAR wsz[3];
*pdw=0;
if(!pwsz)
return FALSE;
if(2 <= wcslen(pwsz))
{
memcpy(wsz, pwsz, 2 * sizeof(WCHAR));
wsz[2]=L'\0';
*pdw=wcstoul(wsz, NULL, 16);
if(ULONG_MAX == *pdw)
*pdw=0;
}
if(*pdw >= CEP_HASH_TABLE_SIZE)
*pdw=0;
return TRUE;
}
//--------------------------------------------------------------------------
//
// CEPSearchPassword
//
//--------------------------------------------------------------------------
CEP_PASSWORD_ENTRY *CEPSearchPassword(LPWSTR pwszPassword, DWORD *pdwIndex)
{
CEP_PASSWORD_ENTRY *pPasswordEntry=NULL;
DWORD dwHashIndex=0;
if(pdwIndex)
*pdwIndex=0;
if(NULL==pwszPassword)
return NULL;
//hash based on the 1st and 2nd character
if(!CEPHashPassword(pwszPassword, &dwHashIndex))
return NULL;
for(pPasswordEntry=g_CEPPasswordTable.rgPasswordEntry[dwHashIndex]; NULL != pPasswordEntry; pPasswordEntry=pPasswordEntry->pNext)
{
if(0==wcscmp(pwszPassword, pPasswordEntry->pwszPassword))
{
break;
}
}
if(pPasswordEntry)
{
if(pdwIndex)
*pdwIndex=dwHashIndex;
}
return pPasswordEntry;
}
//--------------------------------------------------------------------------
//
// CEPInsertValidityEntry
//
//--------------------------------------------------------------------------
BOOL CEPInsertValidityEntry(CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry)
{
if(!pValidityEntry)
return FALSE;
if(g_CEPPasswordTable.pTimeNew)
{
g_CEPPasswordTable.pTimeNew->pNext=pValidityEntry;
pValidityEntry->pPrevious=g_CEPPasswordTable.pTimeNew;
g_CEPPasswordTable.pTimeNew=pValidityEntry;
}
else
{
//no item in the list yet
g_CEPPasswordTable.pTimeOld=pValidityEntry;
g_CEPPasswordTable.pTimeNew=pValidityEntry;
}
return TRUE;
}
//--------------------------------------------------------------------------
//
// CEPInsertPasswordEntry
//
//--------------------------------------------------------------------------
BOOL CEPInsertPasswordEntry(CEP_PASSWORD_ENTRY *pPasswordEntry, DWORD dwHashIndex)
{
if(!pPasswordEntry)
return FALSE;
if(g_CEPPasswordTable.rgPasswordEntry[dwHashIndex])
{
g_CEPPasswordTable.rgPasswordEntry[dwHashIndex]->pPrevious=pPasswordEntry;
pPasswordEntry->pNext=g_CEPPasswordTable.rgPasswordEntry[dwHashIndex];
g_CEPPasswordTable.rgPasswordEntry[dwHashIndex]=pPasswordEntry;
}
else
{
//1st item
g_CEPPasswordTable.rgPasswordEntry[dwHashIndex]=pPasswordEntry;
}
return TRUE;
}
//--------------------------------------------------------------------------
//
// CEPPasswordRemoveValidityEntry
//
//--------------------------------------------------------------------------
BOOL CEPPasswordRemoveValidityEntry(CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry)
{
BOOL fResult=FALSE;
if(!pValidityEntry)
goto InvalidArgErr;
if(pValidityEntry->pPrevious)
pValidityEntry->pPrevious->pNext=pValidityEntry->pNext;
else
{
//1st item
g_CEPPasswordTable.pTimeOld=pValidityEntry->pNext;
}
if(pValidityEntry->pNext)
pValidityEntry->pNext->pPrevious=pValidityEntry->pPrevious;
else
{
//last itme
g_CEPPasswordTable.pTimeNew=pValidityEntry->pPrevious;
}
fResult=TRUE;
CommonReturn:
return fResult;
ErrorReturn:
fResult=FALSE;
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
}
//--------------------------------------------------------------------------
//
// CEPPasswordRemovePasswordEntry
//
//--------------------------------------------------------------------------
BOOL CEPPasswordRemovePasswordEntry(CEP_PASSWORD_ENTRY *pPasswordEntry, DWORD dwIndex)
{
BOOL fResult=FALSE;
if(!pPasswordEntry)
goto InvalidArgErr;
if(pPasswordEntry->pPrevious)
pPasswordEntry->pPrevious->pNext=pPasswordEntry->pNext;
else
g_CEPPasswordTable.rgPasswordEntry[dwIndex]=pPasswordEntry->pNext;
if(pPasswordEntry->pNext)
pPasswordEntry->pNext->pPrevious=pPasswordEntry->pPrevious;
fResult=TRUE;
CommonReturn:
return fResult;
ErrorReturn:
fResult=FALSE;
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
}
//--------------------------------------------------------------------------
//
// CEPPasswordRefresh
//
//--------------------------------------------------------------------------
BOOL CEPPasswordRefresh()
{
BOOL fResult=FALSE;
DWORD dwHashIndex=0;
CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry=NULL;
while(g_CEPPasswordTable.pTimeOld)
{
if(!CEPHashIsCurrentTimeEntry(&(g_CEPPasswordTable.pTimeOld->TimeStamp), 0, g_dwPasswordValidity))
{
if(!CEPHashPassword(g_CEPPasswordTable.pTimeOld->pPasswordEntry->pwszPassword, &dwHashIndex))
{
g_CEPPasswordTable.pTimeOld->pPrevious=NULL;
goto InvalidArgErr;
}
CEPPasswordRemovePasswordEntry(g_CEPPasswordTable.pTimeOld->pPasswordEntry, dwHashIndex);
CEPPasswordFreePasswordEntry(g_CEPPasswordTable.pTimeOld->pPasswordEntry);
pValidityEntry=g_CEPPasswordTable.pTimeOld;
g_CEPPasswordTable.pTimeOld=g_CEPPasswordTable.pTimeOld->pNext;
CEPPasswordFreeValidityEntry(pValidityEntry, FALSE);
if(g_dwPasswordCount >= 1)
g_dwPasswordCount--;
}
else
{
//we find a new enough entry
g_CEPPasswordTable.pTimeOld->pPrevious=NULL;
break;
}
}
//we have get rid of all items
if(NULL == g_CEPPasswordTable.pTimeOld)
{
g_CEPPasswordTable.pTimeNew=NULL;
g_dwPasswordCount=0;
}
fResult=TRUE;
CommonReturn:
return fResult;
ErrorReturn:
fResult=FALSE;
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
}
//***************************************************************************
//
// The following are APIs called by the upper (external) layer
//
//
//***************************************************************************
//--------------------------------------------------------------------------
//
// InitPasswordTable
//
//--------------------------------------------------------------------------
BOOL WINAPI InitPasswordTable()
{
DWORD cbData=0;
DWORD dwData=0;
DWORD dwType=0;
HKEY hKey=NULL;
memset(&g_CEPPasswordTable, 0, sizeof(CEP_PASSWORD_TABLE_INFO));
g_dwPasswordCount=0;
g_dwMaxPassword=CEP_MAX_PASSWORD;
g_dwPasswordValidity=CEP_PASSWORD_VALIDITY;
if(ERROR_SUCCESS == RegOpenKeyExU(
HKEY_LOCAL_MACHINE,
MSCEP_PASSWORD_MAX_LOCATION,
0,
KEY_READ,
&hKey))
{
cbData=sizeof(dwData);
if(ERROR_SUCCESS == RegQueryValueExU(
hKey,
MSCEP_KEY_PASSWORD_MAX,
NULL,
&dwType,
(BYTE *)&dwData,
&cbData))
{
if ((dwType == REG_DWORD) ||
(dwType == REG_BINARY))
{
g_dwMaxPassword=dwData;
}
}
}
dwType=0;
dwData=0;
if(hKey)
RegCloseKey(hKey);
hKey=NULL;
if(ERROR_SUCCESS == RegOpenKeyExU(
HKEY_LOCAL_MACHINE,
MSCEP_PASSWORD_VALIDITY_LOCATION,
0,
KEY_READ,
&hKey))
{
cbData=sizeof(dwData);
if(ERROR_SUCCESS == RegQueryValueExU(
hKey,
MSCEP_KEY_PASSWORD_VALIDITY,
NULL,
&dwType,
(BYTE *)&dwData,
&cbData))
{
if ((dwType == REG_DWORD) ||
(dwType == REG_BINARY))
{
g_dwPasswordValidity=dwData;
}
}
}
if(hKey)
RegCloseKey(hKey);
return TRUE;
}
//--------------------------------------------------------------------------
//
// ReleasePasswordTable
//
//--------------------------------------------------------------------------
BOOL WINAPI ReleasePasswordTable()
{
CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry=NULL;
//free the timestamp list and the password table's doublie linked lists
if(g_CEPPasswordTable.pTimeOld)
{
do{
pValidityEntry=g_CEPPasswordTable.pTimeOld;
g_CEPPasswordTable.pTimeOld = g_CEPPasswordTable.pTimeOld->pNext;
CEPPasswordFreeValidityEntry(pValidityEntry, TRUE);
}
while(g_CEPPasswordTable.pTimeOld);
}
memset(&g_CEPPasswordTable, 0, sizeof(CEP_PASSWORD_TABLE_INFO));
return TRUE;
}
//--------------------------------------------------------------------------
//
// CEPAddPasswordToTable
//
// Need to be protected by the critical section.
//
// Last error is set to CRYPT_E_NO_MATCH if the max number of password is
// reached.
//
//--------------------------------------------------------------------------
BOOL WINAPI CEPAddPasswordToTable(LPWSTR pwszPassword)
{
BOOL fResult=FALSE;
SYSTEMTIME SystemTime;
DWORD dwHashIndex=0;
CEP_PASSWORD_ENTRY *pPasswordEntry=NULL;
CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry=NULL;
EnterCriticalSection(&PasswordCriticalSec);
if(NULL==pwszPassword)
goto InvalidArgErr;
//delete all expired passwords
CEPPasswordRefresh();
if(g_dwPasswordCount >= g_dwMaxPassword)
goto NoMatchErr;
g_dwPasswordCount++;
if(!CEPHashPassword(pwszPassword, &dwHashIndex))
goto InvalidArgErr;
pPasswordEntry=(CEP_PASSWORD_ENTRY *)malloc(sizeof(CEP_PASSWORD_ENTRY));
if(!pPasswordEntry)
goto MemoryErr;
memset(pPasswordEntry, 0, sizeof(CEP_PASSWORD_ENTRY));
pValidityEntry=(CEP_PASSWORD_VALIDITY_ENTRY *)malloc(sizeof(CEP_PASSWORD_VALIDITY_ENTRY));
if(!pValidityEntry)
goto MemoryErr;
memset(pValidityEntry, 0, sizeof(CEP_PASSWORD_VALIDITY_ENTRY));
pPasswordEntry->pwszPassword=(LPWSTR)malloc(sizeof(WCHAR) * (wcslen(pwszPassword)+1));
if(!(pPasswordEntry->pwszPassword))
goto MemoryErr;
wcscpy(pPasswordEntry->pwszPassword,pwszPassword);
//no usage has been requested
pPasswordEntry->dwUsageRequested=0;
pPasswordEntry->pValidityEntry=pValidityEntry;
pPasswordEntry->pNext=NULL;
pPasswordEntry->pPrevious=NULL;
GetSystemTime(&SystemTime);
if(!SystemTimeToFileTime(&SystemTime, &(pValidityEntry->TimeStamp)))
goto TraceErr;
pValidityEntry->pPasswordEntry=pPasswordEntry;
pValidityEntry->pNext=NULL;
pValidityEntry->pPrevious=NULL;
CEPInsertValidityEntry(pValidityEntry);
CEPInsertPasswordEntry(pPasswordEntry, dwHashIndex);
fResult=TRUE;
CommonReturn:
LeaveCriticalSection(&PasswordCriticalSec);
return fResult;
ErrorReturn:
if(pPasswordEntry)
CEPPasswordFreePasswordEntry(pPasswordEntry);
if(pValidityEntry)
CEPPasswordFreeValidityEntry(pValidityEntry, FALSE);
fResult=FALSE;
goto CommonReturn;
SET_ERROR(NoMatchErr, CRYPT_E_NO_MATCH);
TRACE_ERROR(TraceErr);
SET_ERROR(InvalidArgErr, E_INVALIDARG);
SET_ERROR(MemoryErr, E_OUTOFMEMORY);
}
//--------------------------------------------------------------------------
//
// CEPVerifyPasswordAndDeleteFromTable
//
// Need to be protected by the critical section.
//
//--------------------------------------------------------------------------
BOOL WINAPI CEPVerifyPasswordAndDeleteFromTable(LPWSTR pwszPassword, DWORD dwUsage)
{
BOOL fResult=FALSE;
CEP_PASSWORD_ENTRY *pPasswordEntry=NULL;
DWORD dwIndex=0;
EnterCriticalSection(&PasswordCriticalSec);
//delete all expired passwords
CEPPasswordRefresh();
if(NULL == (pPasswordEntry=CEPSearchPassword(pwszPassword, &dwIndex)))
goto InvalidArgErr;
//verify the usage.
//only one signature and one exchange key per password
if(0 != ((pPasswordEntry->dwUsageRequested) & dwUsage))
goto InvalidArgErr;
pPasswordEntry->dwUsageRequested = (pPasswordEntry->dwUsageRequested) | dwUsage;
//remove the password only if both signature and exchange key are requested
if(((pPasswordEntry->dwUsageRequested) & CEP_REQUEST_SIGNATURE) &&
((pPasswordEntry->dwUsageRequested) & CEP_REQUEST_EXCHANGE))
{
CEPPasswordRemoveValidityEntry(pPasswordEntry->pValidityEntry);
CEPPasswordRemovePasswordEntry(pPasswordEntry, dwIndex);
CEPPasswordFreeValidityEntry(pPasswordEntry->pValidityEntry, FALSE);
CEPPasswordFreePasswordEntry(pPasswordEntry);
if(g_dwPasswordCount >= 1)
g_dwPasswordCount--;
}
fResult=TRUE;
CommonReturn:
LeaveCriticalSection(&PasswordCriticalSec);
return fResult;
ErrorReturn:
fResult=FALSE;
goto CommonReturn;
SET_ERROR(InvalidArgErr, E_INVALIDARG);
}