//+------------------------------------------------------------------------- // // Microsoft Windows NT // // Copyright (C) Microsoft Corporation, 1995 - 1998 // // File: ceppswrd.cpp // // Contents: Cisco enrollment protocol implementation. This module // implement the request hash table. // //-------------------------------------------------------------------------- #include "global.hxx" #include DWORD g_dwRequestDuration=0; CEP_REQUEST_TABLE_INFO g_CEPRequestTable; //*************************************************************************** // // The following are APIs called internally. // // //*************************************************************************** //-------------------------------------------------------------------------- // // CEPRequestFreeRequestEntry // //-------------------------------------------------------------------------- void CEPRequestFreeRequestEntry(CEP_REQUEST_ENTRY *pRequestEntry) { if(pRequestEntry) { free(pRequestEntry); } } //-------------------------------------------------------------------------- // // CEPRequestFreeValidityEntry // //-------------------------------------------------------------------------- void CEPRequestFreeValidityEntry(CEP_REQUEST_VALIDITY_ENTRY *pValidityEntry, BOOL fFreeRequestEntry) { if(pValidityEntry) { if(fFreeRequestEntry) CEPRequestFreeRequestEntry(pValidityEntry->pRequestEntry); free(pValidityEntry); } } //-------------------------------------------------------------------------- // // CEPHashRequest // // For any cases that we can not convert the psz, we use index 0. //-------------------------------------------------------------------------- BOOL CEPHashRequest(BYTE *pbHash, DWORD *pdw) { BYTE byte=0; *pdw=0; if(!pbHash) return FALSE; byte=pbHash[0]; *pdw=(DWORD)byte; if(*pdw >= CEP_HASH_TABLE_SIZE) *pdw=0; return TRUE; } //-------------------------------------------------------------------------- // // CEPSearchRequest // //-------------------------------------------------------------------------- CEP_REQUEST_ENTRY *CEPSearchRequest(BYTE *pbHash, DWORD *pdwIndex) { CEP_REQUEST_ENTRY *pRequestEntry=NULL; DWORD dwHashIndex=0; if(pdwIndex) *pdwIndex=0; if(NULL==pbHash) return NULL; //hash based on the 1st byte if(!CEPHashRequest(pbHash, &dwHashIndex)) return NULL; for(pRequestEntry=g_CEPRequestTable.rgRequestEntry[dwHashIndex]; NULL != pRequestEntry; pRequestEntry=pRequestEntry->pNext) { if(0==memcmp(pRequestEntry->pbHash, pbHash, CEP_MD5_HASH_SIZE)) { break; } } if(pRequestEntry) { if(pdwIndex) *pdwIndex=dwHashIndex; } return pRequestEntry; } //-------------------------------------------------------------------------- // // CEPInsertValidityEntry // //-------------------------------------------------------------------------- BOOL CEPInsertValidityEntry(CEP_REQUEST_VALIDITY_ENTRY *pValidityEntry) { if(!pValidityEntry) return FALSE; if(g_CEPRequestTable.pTimeNew) { g_CEPRequestTable.pTimeNew->pNext=pValidityEntry; pValidityEntry->pPrevious=g_CEPRequestTable.pTimeNew; g_CEPRequestTable.pTimeNew=pValidityEntry; } else { //no item in the list yet g_CEPRequestTable.pTimeOld=pValidityEntry; g_CEPRequestTable.pTimeNew=pValidityEntry; } return TRUE; } //-------------------------------------------------------------------------- // // CEPInsertRequestEntry // //-------------------------------------------------------------------------- BOOL CEPInsertRequestEntry(CEP_REQUEST_ENTRY *pRequestEntry, DWORD dwHashIndex) { if(!pRequestEntry) return FALSE; if(g_CEPRequestTable.rgRequestEntry[dwHashIndex]) { g_CEPRequestTable.rgRequestEntry[dwHashIndex]->pPrevious=pRequestEntry; pRequestEntry->pNext=g_CEPRequestTable.rgRequestEntry[dwHashIndex]; g_CEPRequestTable.rgRequestEntry[dwHashIndex]=pRequestEntry; } else { //1st item g_CEPRequestTable.rgRequestEntry[dwHashIndex]=pRequestEntry; } return TRUE; } //-------------------------------------------------------------------------- // // CEPRequestRemoveValidityEntry // //-------------------------------------------------------------------------- BOOL CEPRequestRemoveValidityEntry(CEP_REQUEST_VALIDITY_ENTRY *pValidityEntry) { BOOL fResult=FALSE; if(!pValidityEntry) goto InvalidArgErr; if(pValidityEntry->pPrevious) pValidityEntry->pPrevious->pNext=pValidityEntry->pNext; else { //1st item g_CEPRequestTable.pTimeOld=pValidityEntry->pNext; } if(pValidityEntry->pNext) pValidityEntry->pNext->pPrevious=pValidityEntry->pPrevious; else { //last itme g_CEPRequestTable.pTimeNew=pValidityEntry->pPrevious; } fResult=TRUE; CommonReturn: return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); } //-------------------------------------------------------------------------- // // CEPRequestRemoveRequestEntry // //-------------------------------------------------------------------------- BOOL CEPRequestRemoveRequestEntry(CEP_REQUEST_ENTRY *pRequestEntry, DWORD dwIndex) { BOOL fResult=FALSE; if(!pRequestEntry) goto InvalidArgErr; if(pRequestEntry->pPrevious) pRequestEntry->pPrevious->pNext=pRequestEntry->pNext; else g_CEPRequestTable.rgRequestEntry[dwIndex]=pRequestEntry->pNext; if(pRequestEntry->pNext) pRequestEntry->pNext->pPrevious=pRequestEntry->pPrevious; fResult=TRUE; CommonReturn: return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); } //-------------------------------------------------------------------------- // // CEPRequestRefresh // //-------------------------------------------------------------------------- BOOL CEPRequestRefresh() { BOOL fResult=FALSE; DWORD dwHashIndex=0; CEP_REQUEST_VALIDITY_ENTRY *pValidityEntry=NULL; while(g_CEPRequestTable.pTimeOld) { if(!CEPHashIsCurrentTimeEntry(&(g_CEPRequestTable.pTimeOld->TimeStamp), 0, g_dwRequestDuration)) { if(!CEPHashRequest(g_CEPRequestTable.pTimeOld->pRequestEntry->pbHash, &dwHashIndex)) { g_CEPRequestTable.pTimeOld->pPrevious=NULL; goto InvalidArgErr; } CEPRequestRemoveRequestEntry(g_CEPRequestTable.pTimeOld->pRequestEntry, dwHashIndex); CEPRequestFreeRequestEntry(g_CEPRequestTable.pTimeOld->pRequestEntry); pValidityEntry=g_CEPRequestTable.pTimeOld; g_CEPRequestTable.pTimeOld=g_CEPRequestTable.pTimeOld->pNext; CEPRequestFreeValidityEntry(pValidityEntry, FALSE); } else { //we find a new enough entry g_CEPRequestTable.pTimeOld->pPrevious=NULL; break; } } //we have get rid of all items if(NULL == g_CEPRequestTable.pTimeOld) { g_CEPRequestTable.pTimeNew=NULL; } 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 // // //*************************************************************************** //-------------------------------------------------------------------------- // // InitRequestTable // //-------------------------------------------------------------------------- BOOL WINAPI InitRequestTable() { DWORD cbData=0; DWORD dwData=0; DWORD dwType=0; HKEY hKey=NULL; memset(&g_CEPRequestTable, 0, sizeof(CEP_REQUEST_TABLE_INFO)); g_dwRequestDuration=CEP_REQUEST_DURATION; if(ERROR_SUCCESS == RegOpenKeyExU( HKEY_LOCAL_MACHINE, MSCEP_CACHE_REQUEST_LOCATION, 0, KEY_READ, &hKey)) { cbData=sizeof(dwData); if(ERROR_SUCCESS == RegQueryValueExU( hKey, MSCEP_KEY_CACHE_REQUEST, NULL, &dwType, (BYTE *)&dwData, &cbData)) { if ((dwType == REG_DWORD) || (dwType == REG_BINARY)) { g_dwRequestDuration=dwData; } } } if(hKey) RegCloseKey(hKey); return TRUE; } //-------------------------------------------------------------------------- // // ReleaseRequestTable // //-------------------------------------------------------------------------- BOOL WINAPI ReleaseRequestTable() { CEP_REQUEST_VALIDITY_ENTRY *pValidityEntry=NULL; if(g_CEPRequestTable.pTimeOld) { do{ pValidityEntry=g_CEPRequestTable.pTimeOld; g_CEPRequestTable.pTimeOld = g_CEPRequestTable.pTimeOld->pNext; CEPRequestFreeValidityEntry(pValidityEntry, TRUE); } while(g_CEPRequestTable.pTimeOld); } memset(&g_CEPRequestTable, 0, sizeof(CEP_REQUEST_TABLE_INFO)); return TRUE; } //-------------------------------------------------------------------------- // // CEPRequestRetrieveRequestIDFromHash // //-------------------------------------------------------------------------- BOOL WINAPI CEPRequestRetrieveRequestIDFromHash(BYTE *pbHash, DWORD *pdwRequestID) { BOOL fResult=FALSE; CEP_REQUEST_ENTRY *pRequestEntry=NULL; DWORD dwIndex=0; *pdwRequestID=0; //delete all stale requests CEPRequestRefresh(); if(NULL == (pRequestEntry=CEPSearchRequest(pbHash, &dwIndex))) goto InvalidArgErr; *pdwRequestID=pRequestEntry->dwRequestID; fResult=TRUE; CommonReturn: return fResult; ErrorReturn: fResult=FALSE; goto CommonReturn; SET_ERROR(InvalidArgErr, E_INVALIDARG); } //-------------------------------------------------------------------------- // // CEPRequestAddHashAndRequestID // //-------------------------------------------------------------------------- BOOL WINAPI CEPRequestAddHashAndRequestID(BYTE *pbHash, DWORD dwRequestID) { BOOL fResult=FALSE; SYSTEMTIME SystemTime; DWORD dwHashIndex=0; CEP_REQUEST_ENTRY *pRequestEntry=NULL; CEP_REQUEST_VALIDITY_ENTRY *pValidityEntry=NULL; //delete all stale requests CEPRequestRefresh(); if(!CEPHashRequest(pbHash, &dwHashIndex)) goto InvalidArgErr; pRequestEntry=(CEP_REQUEST_ENTRY *)malloc(sizeof(CEP_REQUEST_ENTRY)); if(!pRequestEntry) goto MemoryErr; memset(pRequestEntry, 0, sizeof(CEP_REQUEST_ENTRY)); pValidityEntry=(CEP_REQUEST_VALIDITY_ENTRY *)malloc(sizeof(CEP_REQUEST_VALIDITY_ENTRY)); if(!pValidityEntry) goto MemoryErr; memset(pValidityEntry, 0, sizeof(CEP_REQUEST_VALIDITY_ENTRY)); memcpy(pRequestEntry->pbHash, pbHash, CEP_MD5_HASH_SIZE); pRequestEntry->dwRequestID=dwRequestID; pRequestEntry->pValidityEntry=pValidityEntry; pRequestEntry->pNext=NULL; pRequestEntry->pPrevious=NULL; GetSystemTime(&SystemTime); if(!SystemTimeToFileTime(&SystemTime, &(pValidityEntry->TimeStamp))) goto TraceErr; pValidityEntry->pRequestEntry=pRequestEntry; pValidityEntry->pNext=NULL; pValidityEntry->pPrevious=NULL; CEPInsertValidityEntry(pValidityEntry); CEPInsertRequestEntry(pRequestEntry, dwHashIndex); fResult=TRUE; CommonReturn: return fResult; ErrorReturn: if(pRequestEntry) CEPRequestFreeRequestEntry(pRequestEntry); if(pValidityEntry) CEPRequestFreeValidityEntry(pValidityEntry, FALSE); fResult=FALSE; goto CommonReturn; TRACE_ERROR(TraceErr); SET_ERROR(InvalidArgErr, E_INVALIDARG); SET_ERROR(MemoryErr, E_OUTOFMEMORY); }