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.

756 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1998
  6. //
  7. // File: cephash.cpp
  8. //
  9. // Contents: Cisco enrollment protocal implementation
  10. //
  11. //--------------------------------------------------------------------------
  12. #include "global.hxx"
  13. #include <dbgdef.h>
  14. CEP_HASH_TABLE_INFO g_CEPHashTable;
  15. //***************************************************************************
  16. //
  17. // The following are APIs called internally.
  18. //
  19. //
  20. //***************************************************************************
  21. //--------------------------------------------------------------------------
  22. //
  23. // CEPHashFreeHashEntry
  24. //
  25. //--------------------------------------------------------------------------
  26. void CEPHashFreeHashEntry(CEP_HASH_ENTRY *pHashEntry)
  27. {
  28. if(pHashEntry)
  29. {
  30. if(pHashEntry->pszTransactionID)
  31. free(pHashEntry->pszTransactionID);
  32. free(pHashEntry);
  33. }
  34. }
  35. //--------------------------------------------------------------------------
  36. //
  37. // CEPHashFreeTimeEntry
  38. //
  39. //--------------------------------------------------------------------------
  40. void CEPHashFreeTimeEntry(CEP_TIME_ENTRY *pTimeEntry, BOOL fFreeHashEntry)
  41. {
  42. if(pTimeEntry)
  43. {
  44. if(fFreeHashEntry)
  45. CEPHashFreeHashEntry(pTimeEntry->pHashEntry);
  46. free(pTimeEntry);
  47. }
  48. }
  49. //--------------------------------------------------------------------------
  50. //
  51. // CEPHashByte
  52. //
  53. // For any cases that we can not convert the psz, we use index 0.
  54. //--------------------------------------------------------------------------
  55. BOOL CEPHashByte(LPSTR psz, DWORD *pdw)
  56. {
  57. CHAR sz[3];
  58. *pdw=0;
  59. if(!psz)
  60. return FALSE;
  61. if(2 <= strlen(psz))
  62. {
  63. memcpy(sz, psz, 2 * sizeof(CHAR));
  64. sz[2]='\0';
  65. *pdw=strtoul(sz, NULL, 16);
  66. if(ULONG_MAX == *pdw)
  67. *pdw=0;
  68. }
  69. if(*pdw >= CEP_HASH_TABLE_SIZE)
  70. *pdw=0;
  71. return TRUE;
  72. }
  73. //--------------------------------------------------------------------------
  74. //
  75. // CEPSearchTransactionID
  76. //
  77. //--------------------------------------------------------------------------
  78. CEP_HASH_ENTRY *CEPSearchTransactionID(CERT_BLOB *pTransactionID, DWORD *pdwIndex)
  79. {
  80. CEP_HASH_ENTRY *pHashEntry=NULL;
  81. DWORD dwHashIndex=0;
  82. if(pdwIndex)
  83. *pdwIndex=0;
  84. if(NULL==pTransactionID->pbData)
  85. return NULL;
  86. //hash based on the 1st and 2nd character
  87. if(!CEPHashByte((LPSTR)(pTransactionID->pbData), &dwHashIndex))
  88. return NULL;
  89. for(pHashEntry=g_CEPHashTable.rgHashEntry[dwHashIndex]; NULL != pHashEntry; pHashEntry=pHashEntry->pNext)
  90. {
  91. if(0==strcmp((LPSTR)(pTransactionID->pbData), pHashEntry->pszTransactionID))
  92. {
  93. break;
  94. }
  95. }
  96. if(pHashEntry)
  97. {
  98. if(pdwIndex)
  99. *pdwIndex=dwHashIndex;
  100. }
  101. return pHashEntry;
  102. }
  103. //--------------------------------------------------------------------------
  104. //
  105. // CEPInsertTimeEntry
  106. //
  107. //--------------------------------------------------------------------------
  108. BOOL CEPInsertTimeEntry(CEP_TIME_ENTRY *pTimeEntry)
  109. {
  110. BOOL fResult=FALSE;
  111. if(g_CEPHashTable.pTimeNew)
  112. {
  113. g_CEPHashTable.pTimeNew->pNext=pTimeEntry;
  114. pTimeEntry->pPrevious=g_CEPHashTable.pTimeNew;
  115. g_CEPHashTable.pTimeNew=pTimeEntry;
  116. }
  117. else
  118. {
  119. //no item in the list yet
  120. g_CEPHashTable.pTimeOld=pTimeEntry;
  121. g_CEPHashTable.pTimeNew=pTimeEntry;
  122. }
  123. fResult=TRUE;
  124. return fResult;
  125. }
  126. //--------------------------------------------------------------------------
  127. //
  128. // CEPInsertHashEntry
  129. //
  130. //--------------------------------------------------------------------------
  131. BOOL CEPInsertHashEntry(CEP_HASH_ENTRY *pHashEntry, DWORD dwHashIndex)
  132. {
  133. BOOL fResult=FALSE;
  134. if(g_CEPHashTable.rgHashEntry[dwHashIndex])
  135. {
  136. g_CEPHashTable.rgHashEntry[dwHashIndex]->pPrevious=pHashEntry;
  137. pHashEntry->pNext=g_CEPHashTable.rgHashEntry[dwHashIndex];
  138. g_CEPHashTable.rgHashEntry[dwHashIndex]=pHashEntry;
  139. }
  140. else
  141. {
  142. //1st item
  143. g_CEPHashTable.rgHashEntry[dwHashIndex]=pHashEntry;
  144. }
  145. fResult=TRUE;
  146. return fResult;
  147. }
  148. //--------------------------------------------------------------------------
  149. //
  150. // CEPHashRemoveTimeEntry
  151. //
  152. //--------------------------------------------------------------------------
  153. BOOL CEPHashRemoveTimeEntry(CEP_TIME_ENTRY *pTimeEntry)
  154. {
  155. BOOL fResult=FALSE;
  156. if(!pTimeEntry)
  157. goto InvalidArgErr;
  158. if(pTimeEntry->pPrevious)
  159. pTimeEntry->pPrevious->pNext=pTimeEntry->pNext;
  160. else
  161. {
  162. //1st item
  163. g_CEPHashTable.pTimeOld=pTimeEntry->pNext;
  164. }
  165. if(pTimeEntry->pNext)
  166. pTimeEntry->pNext->pPrevious=pTimeEntry->pPrevious;
  167. else
  168. {
  169. //last itme
  170. g_CEPHashTable.pTimeNew=pTimeEntry->pPrevious;
  171. }
  172. fResult=TRUE;
  173. CommonReturn:
  174. return fResult;
  175. ErrorReturn:
  176. fResult=FALSE;
  177. goto CommonReturn;
  178. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  179. }
  180. //--------------------------------------------------------------------------
  181. //
  182. // CEPHashRemoveHashEntry
  183. //
  184. //--------------------------------------------------------------------------
  185. BOOL CEPHashRemoveHashEntry(CEP_HASH_ENTRY *pHashEntry, DWORD dwIndex)
  186. {
  187. BOOL fResult=FALSE;
  188. if(!pHashEntry)
  189. goto InvalidArgErr;
  190. if(pHashEntry->pPrevious)
  191. pHashEntry->pPrevious->pNext=pHashEntry->pNext;
  192. else
  193. g_CEPHashTable.rgHashEntry[dwIndex]=pHashEntry->pNext;
  194. if(pHashEntry->pNext)
  195. pHashEntry->pNext->pPrevious=pHashEntry->pPrevious;
  196. fResult=TRUE;
  197. CommonReturn:
  198. return fResult;
  199. ErrorReturn:
  200. fResult=FALSE;
  201. goto CommonReturn;
  202. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  203. }
  204. //--------------------------------------------------------------------------
  205. //
  206. // CEPHashCheckCurrentTime
  207. //
  208. // If we are still waiting for the pending results, use the default
  209. // waiting time, otherwise, use the cach time
  210. //--------------------------------------------------------------------------
  211. BOOL CEPHashCheckCurrentTime(FILETIME *pTimeStamp, BOOL fFinished, DWORD dwRefreshDays)
  212. {
  213. DWORD dwDays=0;
  214. DWORD dwMinutes=0;
  215. if(fFinished)
  216. {
  217. dwMinutes=g_dwRequestDuration;
  218. }
  219. else
  220. {
  221. dwDays=dwRefreshDays;
  222. }
  223. return CEPHashIsCurrentTimeEntry(pTimeStamp, dwDays, dwMinutes);
  224. }
  225. //--------------------------------------------------------------------------
  226. //
  227. // CEPHashIsCurrentTimeEntry
  228. //
  229. // If anything went wrong, we think the time entry is not current.
  230. //--------------------------------------------------------------------------
  231. BOOL CEPHashIsCurrentTimeEntry(FILETIME *pTimeStamp, DWORD dwRefreshDays, DWORD dwMinutes)
  232. {
  233. BOOL fCurrent=FALSE;
  234. SYSTEMTIME SystemTime;
  235. FILETIME CurrentTime;
  236. ULARGE_INTEGER dwSeconds;
  237. ULARGE_INTEGER OldTime;
  238. FILETIME UpdatedTimeStamp;
  239. if(!pTimeStamp)
  240. goto CLEANUP;
  241. GetSystemTime(&SystemTime);
  242. if(!SystemTimeToFileTime(&SystemTime, &(CurrentTime)))
  243. goto CLEANUP;
  244. //add the # of seconds
  245. //// FILETIME is in units of 100 nanoseconds (10**-7)
  246. if(dwRefreshDays)
  247. dwSeconds.QuadPart=dwRefreshDays * 24 * 3600;
  248. else
  249. dwSeconds.QuadPart=dwMinutes * 60;
  250. dwSeconds.QuadPart=dwSeconds.QuadPart * 10000000;
  251. OldTime.LowPart=pTimeStamp->dwLowDateTime;
  252. OldTime.HighPart=pTimeStamp->dwHighDateTime;
  253. OldTime.QuadPart = OldTime.QuadPart + dwSeconds.QuadPart;
  254. UpdatedTimeStamp.dwLowDateTime=OldTime.LowPart;
  255. UpdatedTimeStamp.dwHighDateTime=OldTime.HighPart;
  256. //1 means CurrentTime is greater than the UpdatedTimeStamp
  257. if( 1 == CompareFileTime(&CurrentTime, &UpdatedTimeStamp))
  258. goto CLEANUP;
  259. fCurrent=TRUE;
  260. CLEANUP:
  261. return fCurrent;
  262. }
  263. //--------------------------------------------------------------------------
  264. //
  265. // CEPHashRefresh
  266. //
  267. //--------------------------------------------------------------------------
  268. BOOL CEPHashRefresh(DWORD dwRefreshDays)
  269. {
  270. BOOL fResult=FALSE;
  271. DWORD dwHashIndex=0;
  272. CEP_TIME_ENTRY *pTimeEntry=NULL;
  273. while(g_CEPHashTable.pTimeOld)
  274. {
  275. if(!CEPHashCheckCurrentTime(&(g_CEPHashTable.pTimeOld->TimeStamp), g_CEPHashTable.pTimeOld->pHashEntry->fFinished, dwRefreshDays))
  276. {
  277. if(!CEPHashByte(g_CEPHashTable.pTimeOld->pHashEntry->pszTransactionID, &dwHashIndex))
  278. {
  279. g_CEPHashTable.pTimeOld->pPrevious=NULL;
  280. goto InvalidArgErr;
  281. }
  282. CEPHashRemoveHashEntry(g_CEPHashTable.pTimeOld->pHashEntry, dwHashIndex);
  283. CEPHashFreeHashEntry(g_CEPHashTable.pTimeOld->pHashEntry);
  284. pTimeEntry=g_CEPHashTable.pTimeOld;
  285. g_CEPHashTable.pTimeOld=g_CEPHashTable.pTimeOld->pNext;
  286. CEPHashFreeTimeEntry(pTimeEntry, FALSE);
  287. }
  288. else
  289. {
  290. //we find a new enough entry
  291. g_CEPHashTable.pTimeOld->pPrevious=NULL;
  292. break;
  293. }
  294. }
  295. //we have get rid of all items
  296. if(NULL == g_CEPHashTable.pTimeOld)
  297. g_CEPHashTable.pTimeNew=NULL;
  298. fResult=TRUE;
  299. CommonReturn:
  300. return fResult;
  301. ErrorReturn:
  302. fResult=FALSE;
  303. goto CommonReturn;
  304. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  305. }
  306. //***************************************************************************
  307. //
  308. // The following are APIs called by the upper (external) layer
  309. //
  310. //
  311. //***************************************************************************
  312. //
  313. // Function called without critical section protection
  314. //
  315. //--------------------------------------------------------------------------
  316. //
  317. // InitHashTable
  318. //
  319. //--------------------------------------------------------------------------
  320. BOOL InitHashTable()
  321. {
  322. memset(&g_CEPHashTable, 0, sizeof(CEP_HASH_TABLE_INFO));
  323. return TRUE;
  324. }
  325. //--------------------------------------------------------------------------
  326. //
  327. // ReleaseHashTable
  328. //
  329. //--------------------------------------------------------------------------
  330. BOOL ReleaseHashTable()
  331. {
  332. CEP_TIME_ENTRY *pTimeEntry=NULL;
  333. //free the timestamp list and the hash table's doublie linked lists
  334. if(g_CEPHashTable.pTimeOld)
  335. {
  336. do{
  337. pTimeEntry=g_CEPHashTable.pTimeOld;
  338. g_CEPHashTable.pTimeOld = g_CEPHashTable.pTimeOld->pNext;
  339. //free both the time entry and the hash entry
  340. CEPHashFreeTimeEntry(pTimeEntry, TRUE);
  341. }
  342. while(g_CEPHashTable.pTimeOld);
  343. }
  344. memset(&g_CEPHashTable, 0, sizeof(CEP_HASH_TABLE_INFO));
  345. return TRUE;
  346. }
  347. //
  348. // Function called with critical section protection
  349. //
  350. //--------------------------------------------------------------------------
  351. //
  352. // CEPHashGetRequestID
  353. //
  354. // Retriev the MS Cert Server's requestID based on the transaction ID
  355. //--------------------------------------------------------------------------
  356. BOOL CEPHashGetRequestID( DWORD dwRefreshDays,
  357. CERT_BLOB *pTransactionID,
  358. DWORD *pdwRequestID)
  359. {
  360. BOOL fResult=FALSE;
  361. CEP_HASH_ENTRY *pHashEntry=NULL;
  362. *pdwRequestID=0;
  363. //we refresh the time list so that we only keep most up-to-date entries
  364. if(0 != dwRefreshDays)
  365. CEPHashRefresh(dwRefreshDays);
  366. if(NULL == (pHashEntry=CEPSearchTransactionID(pTransactionID, NULL)))
  367. goto InvalidArgErr;
  368. //we do not process the stable items. They could exit due to the
  369. //20 minutes buffer
  370. if(!CEPHashCheckCurrentTime(&(pHashEntry->pTimeEntry->TimeStamp),
  371. pHashEntry->fFinished,
  372. dwRefreshDays))
  373. goto InvalidArgErr;
  374. *pdwRequestID=pHashEntry->dwRequestID;
  375. fResult=TRUE;
  376. CommonReturn:
  377. return fResult;
  378. ErrorReturn:
  379. fResult=FALSE;
  380. goto CommonReturn;
  381. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  382. }
  383. //--------------------------------------------------------------------------
  384. //
  385. // CEPHashRemoveRequestAndTransaction
  386. //
  387. //
  388. //--------------------------------------------------------------------------
  389. BOOL CEPHashRemoveRequestAndTransaction(DWORD dwRequestID, CERT_BLOB *pTransactionID)
  390. {
  391. BOOL fResult=FALSE;
  392. CEP_HASH_ENTRY *pHashEntry=NULL;
  393. DWORD dwIndex=0;
  394. if(NULL == (pHashEntry=CEPSearchTransactionID(pTransactionID, &dwIndex)))
  395. goto InvalidArgErr;
  396. CEPHashRemoveTimeEntry(pHashEntry->pTimeEntry);
  397. CEPHashRemoveHashEntry(pHashEntry, dwIndex);
  398. CEPHashFreeTimeEntry(pHashEntry->pTimeEntry, FALSE);
  399. CEPHashFreeHashEntry(pHashEntry);
  400. fResult=TRUE;
  401. CommonReturn:
  402. return fResult;
  403. ErrorReturn:
  404. fResult=FALSE;
  405. goto CommonReturn;
  406. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  407. }
  408. //--------------------------------------------------------------------------
  409. //
  410. // CEPHashMarkTransactionFinished
  411. //
  412. //
  413. //--------------------------------------------------------------------------
  414. BOOL CEPHashMarkTransactionFinished(DWORD dwRequestID, CERT_BLOB *pTransactionID)
  415. {
  416. BOOL fResult=FALSE;
  417. CEP_HASH_ENTRY *pHashEntry=NULL;
  418. DWORD dwIndex=0;
  419. SYSTEMTIME SystemTime;
  420. if(NULL == (pHashEntry=CEPSearchTransactionID(pTransactionID, &dwIndex)))
  421. goto InvalidArgErr;
  422. pHashEntry->fFinished=TRUE;
  423. //re-timestamp the entry since it should last for another 20 minutes for
  424. //retrial cases
  425. GetSystemTime(&SystemTime);
  426. if(!SystemTimeToFileTime(&SystemTime, &(pHashEntry->pTimeEntry->TimeStamp)))
  427. goto InvalidArgErr;
  428. fResult=TRUE;
  429. CommonReturn:
  430. return fResult;
  431. ErrorReturn:
  432. fResult=FALSE;
  433. goto CommonReturn;
  434. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  435. }
  436. //--------------------------------------------------------------------------
  437. //
  438. // AddRequestAndTransaction
  439. //
  440. // Add a requestID and TransactionID pair
  441. //--------------------------------------------------------------------------
  442. BOOL CEPHashAddRequestAndTransaction(DWORD dwRefreshDays,
  443. DWORD dwRequestID,
  444. CERT_BLOB *pTransactionID)
  445. {
  446. BOOL fResult=FALSE;
  447. SYSTEMTIME SystemTime;
  448. DWORD dwHashIndex=0;
  449. CEP_HASH_ENTRY *pHashEntry=NULL;
  450. CEP_TIME_ENTRY *pTimeEntry=NULL;
  451. //remove the old requestID/transactionID pair
  452. CEPHashRemoveRequestAndTransaction(dwRequestID, pTransactionID);
  453. if(!CEPHashByte((LPSTR)(pTransactionID->pbData), &dwHashIndex))
  454. goto InvalidArgErr;
  455. pHashEntry=(CEP_HASH_ENTRY *)malloc(sizeof(CEP_HASH_ENTRY));
  456. if(!pHashEntry)
  457. goto MemoryErr;
  458. memset(pHashEntry, 0, sizeof(CEP_HASH_ENTRY));
  459. pTimeEntry=(CEP_TIME_ENTRY *)malloc(sizeof(CEP_TIME_ENTRY));
  460. if(!pTimeEntry)
  461. goto MemoryErr;
  462. memset(pTimeEntry, 0, sizeof(CEP_TIME_ENTRY));
  463. pHashEntry->pszTransactionID=(LPSTR)malloc(strlen((LPSTR)(pTransactionID->pbData))+1);
  464. if(!(pHashEntry->pszTransactionID))
  465. goto MemoryErr;
  466. strcpy(pHashEntry->pszTransactionID,(LPSTR)(pTransactionID->pbData));
  467. pHashEntry->dwRequestID=dwRequestID;
  468. pHashEntry->fFinished=FALSE;
  469. pHashEntry->pTimeEntry=pTimeEntry;
  470. pHashEntry->pNext=NULL;
  471. pHashEntry->pPrevious=NULL;
  472. GetSystemTime(&SystemTime);
  473. if(!SystemTimeToFileTime(&SystemTime, &(pTimeEntry->TimeStamp)))
  474. goto TraceErr;
  475. pTimeEntry->pHashEntry=pHashEntry;
  476. pTimeEntry->pNext=NULL;
  477. pTimeEntry->pPrevious=NULL;
  478. CEPInsertTimeEntry(pTimeEntry);
  479. CEPInsertHashEntry(pHashEntry, dwHashIndex);
  480. //we refresh the time list so that we only keep most up-to-date entries
  481. if(0 != dwRefreshDays)
  482. CEPHashRefresh(dwRefreshDays);
  483. fResult=TRUE;
  484. CommonReturn:
  485. return fResult;
  486. ErrorReturn:
  487. if(pHashEntry)
  488. CEPHashFreeHashEntry(pHashEntry);
  489. if(pTimeEntry)
  490. CEPHashFreeTimeEntry(pTimeEntry, FALSE);
  491. fResult=FALSE;
  492. goto CommonReturn;
  493. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  494. TRACE_ERROR(TraceErr);
  495. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  496. }
  497. //***************************************************************************
  498. //
  499. // obsolete
  500. //
  501. //
  502. //***************************************************************************
  503. /*
  504. //TODO: Send to database later
  505. //DWORD g_dwRequestID=0;
  506. //CERT_BLOB g_TransactionID={0, NULL};
  507. //--------------------------------------------------------------------------
  508. //
  509. // GetRequestID
  510. //
  511. // TODO: we need to call the database layer in this case
  512. //--------------------------------------------------------------------------
  513. BOOL GetRequestID(CERT_BLOB *pTransactionID,
  514. DWORD *pdwRequestID)
  515. {
  516. *pdwRequestID=0;
  517. if(NULL==pTransactionID->pbData)
  518. return FALSE;
  519. //make sure we have the correct transaction ID
  520. if(0!=strcmp((LPSTR)(pTransactionID->pbData), (LPSTR)(g_TransactionID.pbData)))
  521. return FALSE;
  522. *pdwRequestID=g_dwRequestID;
  523. return TRUE;
  524. }
  525. //--------------------------------------------------------------------------
  526. //
  527. // DeleteRequestAndTransaction
  528. //
  529. // TODO: we need to call the database layer in this case
  530. //--------------------------------------------------------------------------
  531. BOOL DeleteRequestAndTransaction(DWORD dwRequestID, CERT_BLOB *pTransactionID)
  532. {
  533. g_dwRequestID=0;
  534. if(g_TransactionID.pbData)
  535. free(g_TransactionID.pbData);
  536. g_TransactionID.pbData=NULL;
  537. g_TransactionID.cbData=0;
  538. return TRUE;
  539. }
  540. //--------------------------------------------------------------------------
  541. //
  542. // CopyRequestAndTransaction
  543. //
  544. // TODO: we need to call the database layer in this case
  545. //--------------------------------------------------------------------------
  546. BOOL CopyRequestAndTransaction(DWORD dwRequestID, CERT_BLOB *pTransactionID)
  547. {
  548. //delete the old requestID/transactionID pair
  549. DeleteRequestAndTransaction(dwRequestID, pTransactionID);
  550. g_dwRequestID=dwRequestID;
  551. g_TransactionID.pbData=(BYTE *)malloc(strlen((LPSTR)(pTransactionID->pbData))+1);
  552. if(NULL == g_TransactionID.pbData)
  553. {
  554. SetLastError(E_OUTOFMEMORY);
  555. return FALSE;
  556. }
  557. g_TransactionID.cbData=strlen((LPSTR)(pTransactionID->pbData));
  558. memcpy(g_TransactionID.pbData, (LPSTR)(pTransactionID->pbData), g_TransactionID.cbData+1);
  559. return TRUE;
  560. } */