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

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1998
  6. //
  7. // File: ceppswrd.cpp
  8. //
  9. // Contents: Cisco enrollment protocol implementation. This module
  10. // implement the password hash table.
  11. //
  12. //--------------------------------------------------------------------------
  13. #include "global.hxx"
  14. #include <dbgdef.h>
  15. DWORD g_dwPasswordCount=0;
  16. DWORD g_dwMaxPassword=0;
  17. DWORD g_dwPasswordValidity=0;
  18. CEP_PASSWORD_TABLE_INFO g_CEPPasswordTable;
  19. //***************************************************************************
  20. //
  21. // The following are APIs called internally.
  22. //
  23. //
  24. //***************************************************************************
  25. //--------------------------------------------------------------------------
  26. //
  27. // CEPPasswordFreePasswordEntry
  28. //
  29. //--------------------------------------------------------------------------
  30. void CEPPasswordFreePasswordEntry(CEP_PASSWORD_ENTRY *pPasswordEntry)
  31. {
  32. if(pPasswordEntry)
  33. {
  34. if(pPasswordEntry->pwszPassword)
  35. free(pPasswordEntry->pwszPassword);
  36. free(pPasswordEntry);
  37. }
  38. }
  39. //--------------------------------------------------------------------------
  40. //
  41. // CEPPasswordFreeValidityEntry
  42. //
  43. //--------------------------------------------------------------------------
  44. void CEPPasswordFreeValidityEntry(CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry,
  45. BOOL fFreePasswordEntry)
  46. {
  47. if(pValidityEntry)
  48. {
  49. if(fFreePasswordEntry)
  50. CEPPasswordFreePasswordEntry(pValidityEntry->pPasswordEntry);
  51. free(pValidityEntry);
  52. }
  53. }
  54. //--------------------------------------------------------------------------
  55. //
  56. // CEPHashPassword
  57. //
  58. // For any cases that we can not convert the psz, we use index 0.
  59. //--------------------------------------------------------------------------
  60. BOOL CEPHashPassword(LPWSTR pwsz, DWORD *pdw)
  61. {
  62. WCHAR wsz[3];
  63. *pdw=0;
  64. if(!pwsz)
  65. return FALSE;
  66. if(2 <= wcslen(pwsz))
  67. {
  68. memcpy(wsz, pwsz, 2 * sizeof(WCHAR));
  69. wsz[2]=L'\0';
  70. *pdw=wcstoul(wsz, NULL, 16);
  71. if(ULONG_MAX == *pdw)
  72. *pdw=0;
  73. }
  74. if(*pdw >= CEP_HASH_TABLE_SIZE)
  75. *pdw=0;
  76. return TRUE;
  77. }
  78. //--------------------------------------------------------------------------
  79. //
  80. // CEPSearchPassword
  81. //
  82. //--------------------------------------------------------------------------
  83. CEP_PASSWORD_ENTRY *CEPSearchPassword(LPWSTR pwszPassword, DWORD *pdwIndex)
  84. {
  85. CEP_PASSWORD_ENTRY *pPasswordEntry=NULL;
  86. DWORD dwHashIndex=0;
  87. if(pdwIndex)
  88. *pdwIndex=0;
  89. if(NULL==pwszPassword)
  90. return NULL;
  91. //hash based on the 1st and 2nd character
  92. if(!CEPHashPassword(pwszPassword, &dwHashIndex))
  93. return NULL;
  94. for(pPasswordEntry=g_CEPPasswordTable.rgPasswordEntry[dwHashIndex]; NULL != pPasswordEntry; pPasswordEntry=pPasswordEntry->pNext)
  95. {
  96. if(0==wcscmp(pwszPassword, pPasswordEntry->pwszPassword))
  97. {
  98. break;
  99. }
  100. }
  101. if(pPasswordEntry)
  102. {
  103. if(pdwIndex)
  104. *pdwIndex=dwHashIndex;
  105. }
  106. return pPasswordEntry;
  107. }
  108. //--------------------------------------------------------------------------
  109. //
  110. // CEPInsertValidityEntry
  111. //
  112. //--------------------------------------------------------------------------
  113. BOOL CEPInsertValidityEntry(CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry)
  114. {
  115. if(!pValidityEntry)
  116. return FALSE;
  117. if(g_CEPPasswordTable.pTimeNew)
  118. {
  119. g_CEPPasswordTable.pTimeNew->pNext=pValidityEntry;
  120. pValidityEntry->pPrevious=g_CEPPasswordTable.pTimeNew;
  121. g_CEPPasswordTable.pTimeNew=pValidityEntry;
  122. }
  123. else
  124. {
  125. //no item in the list yet
  126. g_CEPPasswordTable.pTimeOld=pValidityEntry;
  127. g_CEPPasswordTable.pTimeNew=pValidityEntry;
  128. }
  129. return TRUE;
  130. }
  131. //--------------------------------------------------------------------------
  132. //
  133. // CEPInsertPasswordEntry
  134. //
  135. //--------------------------------------------------------------------------
  136. BOOL CEPInsertPasswordEntry(CEP_PASSWORD_ENTRY *pPasswordEntry, DWORD dwHashIndex)
  137. {
  138. if(!pPasswordEntry)
  139. return FALSE;
  140. if(g_CEPPasswordTable.rgPasswordEntry[dwHashIndex])
  141. {
  142. g_CEPPasswordTable.rgPasswordEntry[dwHashIndex]->pPrevious=pPasswordEntry;
  143. pPasswordEntry->pNext=g_CEPPasswordTable.rgPasswordEntry[dwHashIndex];
  144. g_CEPPasswordTable.rgPasswordEntry[dwHashIndex]=pPasswordEntry;
  145. }
  146. else
  147. {
  148. //1st item
  149. g_CEPPasswordTable.rgPasswordEntry[dwHashIndex]=pPasswordEntry;
  150. }
  151. return TRUE;
  152. }
  153. //--------------------------------------------------------------------------
  154. //
  155. // CEPPasswordRemoveValidityEntry
  156. //
  157. //--------------------------------------------------------------------------
  158. BOOL CEPPasswordRemoveValidityEntry(CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry)
  159. {
  160. BOOL fResult=FALSE;
  161. if(!pValidityEntry)
  162. goto InvalidArgErr;
  163. if(pValidityEntry->pPrevious)
  164. pValidityEntry->pPrevious->pNext=pValidityEntry->pNext;
  165. else
  166. {
  167. //1st item
  168. g_CEPPasswordTable.pTimeOld=pValidityEntry->pNext;
  169. }
  170. if(pValidityEntry->pNext)
  171. pValidityEntry->pNext->pPrevious=pValidityEntry->pPrevious;
  172. else
  173. {
  174. //last itme
  175. g_CEPPasswordTable.pTimeNew=pValidityEntry->pPrevious;
  176. }
  177. fResult=TRUE;
  178. CommonReturn:
  179. return fResult;
  180. ErrorReturn:
  181. fResult=FALSE;
  182. goto CommonReturn;
  183. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  184. }
  185. //--------------------------------------------------------------------------
  186. //
  187. // CEPPasswordRemovePasswordEntry
  188. //
  189. //--------------------------------------------------------------------------
  190. BOOL CEPPasswordRemovePasswordEntry(CEP_PASSWORD_ENTRY *pPasswordEntry, DWORD dwIndex)
  191. {
  192. BOOL fResult=FALSE;
  193. if(!pPasswordEntry)
  194. goto InvalidArgErr;
  195. if(pPasswordEntry->pPrevious)
  196. pPasswordEntry->pPrevious->pNext=pPasswordEntry->pNext;
  197. else
  198. g_CEPPasswordTable.rgPasswordEntry[dwIndex]=pPasswordEntry->pNext;
  199. if(pPasswordEntry->pNext)
  200. pPasswordEntry->pNext->pPrevious=pPasswordEntry->pPrevious;
  201. fResult=TRUE;
  202. CommonReturn:
  203. return fResult;
  204. ErrorReturn:
  205. fResult=FALSE;
  206. goto CommonReturn;
  207. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  208. }
  209. //--------------------------------------------------------------------------
  210. //
  211. // CEPPasswordRefresh
  212. //
  213. //--------------------------------------------------------------------------
  214. BOOL CEPPasswordRefresh()
  215. {
  216. BOOL fResult=FALSE;
  217. DWORD dwHashIndex=0;
  218. CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry=NULL;
  219. while(g_CEPPasswordTable.pTimeOld)
  220. {
  221. if(!CEPHashIsCurrentTimeEntry(&(g_CEPPasswordTable.pTimeOld->TimeStamp), 0, g_dwPasswordValidity))
  222. {
  223. if(!CEPHashPassword(g_CEPPasswordTable.pTimeOld->pPasswordEntry->pwszPassword, &dwHashIndex))
  224. {
  225. g_CEPPasswordTable.pTimeOld->pPrevious=NULL;
  226. goto InvalidArgErr;
  227. }
  228. CEPPasswordRemovePasswordEntry(g_CEPPasswordTable.pTimeOld->pPasswordEntry, dwHashIndex);
  229. CEPPasswordFreePasswordEntry(g_CEPPasswordTable.pTimeOld->pPasswordEntry);
  230. pValidityEntry=g_CEPPasswordTable.pTimeOld;
  231. g_CEPPasswordTable.pTimeOld=g_CEPPasswordTable.pTimeOld->pNext;
  232. CEPPasswordFreeValidityEntry(pValidityEntry, FALSE);
  233. if(g_dwPasswordCount >= 1)
  234. g_dwPasswordCount--;
  235. }
  236. else
  237. {
  238. //we find a new enough entry
  239. g_CEPPasswordTable.pTimeOld->pPrevious=NULL;
  240. break;
  241. }
  242. }
  243. //we have get rid of all items
  244. if(NULL == g_CEPPasswordTable.pTimeOld)
  245. {
  246. g_CEPPasswordTable.pTimeNew=NULL;
  247. g_dwPasswordCount=0;
  248. }
  249. fResult=TRUE;
  250. CommonReturn:
  251. return fResult;
  252. ErrorReturn:
  253. fResult=FALSE;
  254. goto CommonReturn;
  255. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  256. }
  257. //***************************************************************************
  258. //
  259. // The following are APIs called by the upper (external) layer
  260. //
  261. //
  262. //***************************************************************************
  263. //--------------------------------------------------------------------------
  264. //
  265. // InitPasswordTable
  266. //
  267. //--------------------------------------------------------------------------
  268. BOOL WINAPI InitPasswordTable()
  269. {
  270. DWORD cbData=0;
  271. DWORD dwData=0;
  272. DWORD dwType=0;
  273. HKEY hKey=NULL;
  274. memset(&g_CEPPasswordTable, 0, sizeof(CEP_PASSWORD_TABLE_INFO));
  275. g_dwPasswordCount=0;
  276. g_dwMaxPassword=CEP_MAX_PASSWORD;
  277. g_dwPasswordValidity=CEP_PASSWORD_VALIDITY;
  278. if(ERROR_SUCCESS == RegOpenKeyExU(
  279. HKEY_LOCAL_MACHINE,
  280. MSCEP_PASSWORD_MAX_LOCATION,
  281. 0,
  282. KEY_READ,
  283. &hKey))
  284. {
  285. cbData=sizeof(dwData);
  286. if(ERROR_SUCCESS == RegQueryValueExU(
  287. hKey,
  288. MSCEP_KEY_PASSWORD_MAX,
  289. NULL,
  290. &dwType,
  291. (BYTE *)&dwData,
  292. &cbData))
  293. {
  294. if ((dwType == REG_DWORD) ||
  295. (dwType == REG_BINARY))
  296. {
  297. g_dwMaxPassword=dwData;
  298. }
  299. }
  300. }
  301. dwType=0;
  302. dwData=0;
  303. if(hKey)
  304. RegCloseKey(hKey);
  305. hKey=NULL;
  306. if(ERROR_SUCCESS == RegOpenKeyExU(
  307. HKEY_LOCAL_MACHINE,
  308. MSCEP_PASSWORD_VALIDITY_LOCATION,
  309. 0,
  310. KEY_READ,
  311. &hKey))
  312. {
  313. cbData=sizeof(dwData);
  314. if(ERROR_SUCCESS == RegQueryValueExU(
  315. hKey,
  316. MSCEP_KEY_PASSWORD_VALIDITY,
  317. NULL,
  318. &dwType,
  319. (BYTE *)&dwData,
  320. &cbData))
  321. {
  322. if ((dwType == REG_DWORD) ||
  323. (dwType == REG_BINARY))
  324. {
  325. g_dwPasswordValidity=dwData;
  326. }
  327. }
  328. }
  329. if(hKey)
  330. RegCloseKey(hKey);
  331. return TRUE;
  332. }
  333. //--------------------------------------------------------------------------
  334. //
  335. // ReleasePasswordTable
  336. //
  337. //--------------------------------------------------------------------------
  338. BOOL WINAPI ReleasePasswordTable()
  339. {
  340. CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry=NULL;
  341. //free the timestamp list and the password table's doublie linked lists
  342. if(g_CEPPasswordTable.pTimeOld)
  343. {
  344. do{
  345. pValidityEntry=g_CEPPasswordTable.pTimeOld;
  346. g_CEPPasswordTable.pTimeOld = g_CEPPasswordTable.pTimeOld->pNext;
  347. CEPPasswordFreeValidityEntry(pValidityEntry, TRUE);
  348. }
  349. while(g_CEPPasswordTable.pTimeOld);
  350. }
  351. memset(&g_CEPPasswordTable, 0, sizeof(CEP_PASSWORD_TABLE_INFO));
  352. return TRUE;
  353. }
  354. //--------------------------------------------------------------------------
  355. //
  356. // CEPAddPasswordToTable
  357. //
  358. // Need to be protected by the critical section.
  359. //
  360. // Last error is set to CRYPT_E_NO_MATCH if the max number of password is
  361. // reached.
  362. //
  363. //--------------------------------------------------------------------------
  364. BOOL WINAPI CEPAddPasswordToTable(LPWSTR pwszPassword)
  365. {
  366. BOOL fResult=FALSE;
  367. SYSTEMTIME SystemTime;
  368. DWORD dwHashIndex=0;
  369. CEP_PASSWORD_ENTRY *pPasswordEntry=NULL;
  370. CEP_PASSWORD_VALIDITY_ENTRY *pValidityEntry=NULL;
  371. EnterCriticalSection(&PasswordCriticalSec);
  372. if(NULL==pwszPassword)
  373. goto InvalidArgErr;
  374. //delete all expired passwords
  375. CEPPasswordRefresh();
  376. if(g_dwPasswordCount >= g_dwMaxPassword)
  377. goto NoMatchErr;
  378. g_dwPasswordCount++;
  379. if(!CEPHashPassword(pwszPassword, &dwHashIndex))
  380. goto InvalidArgErr;
  381. pPasswordEntry=(CEP_PASSWORD_ENTRY *)malloc(sizeof(CEP_PASSWORD_ENTRY));
  382. if(!pPasswordEntry)
  383. goto MemoryErr;
  384. memset(pPasswordEntry, 0, sizeof(CEP_PASSWORD_ENTRY));
  385. pValidityEntry=(CEP_PASSWORD_VALIDITY_ENTRY *)malloc(sizeof(CEP_PASSWORD_VALIDITY_ENTRY));
  386. if(!pValidityEntry)
  387. goto MemoryErr;
  388. memset(pValidityEntry, 0, sizeof(CEP_PASSWORD_VALIDITY_ENTRY));
  389. pPasswordEntry->pwszPassword=(LPWSTR)malloc(sizeof(WCHAR) * (wcslen(pwszPassword)+1));
  390. if(!(pPasswordEntry->pwszPassword))
  391. goto MemoryErr;
  392. wcscpy(pPasswordEntry->pwszPassword,pwszPassword);
  393. //no usage has been requested
  394. pPasswordEntry->dwUsageRequested=0;
  395. pPasswordEntry->pValidityEntry=pValidityEntry;
  396. pPasswordEntry->pNext=NULL;
  397. pPasswordEntry->pPrevious=NULL;
  398. GetSystemTime(&SystemTime);
  399. if(!SystemTimeToFileTime(&SystemTime, &(pValidityEntry->TimeStamp)))
  400. goto TraceErr;
  401. pValidityEntry->pPasswordEntry=pPasswordEntry;
  402. pValidityEntry->pNext=NULL;
  403. pValidityEntry->pPrevious=NULL;
  404. CEPInsertValidityEntry(pValidityEntry);
  405. CEPInsertPasswordEntry(pPasswordEntry, dwHashIndex);
  406. fResult=TRUE;
  407. CommonReturn:
  408. LeaveCriticalSection(&PasswordCriticalSec);
  409. return fResult;
  410. ErrorReturn:
  411. if(pPasswordEntry)
  412. CEPPasswordFreePasswordEntry(pPasswordEntry);
  413. if(pValidityEntry)
  414. CEPPasswordFreeValidityEntry(pValidityEntry, FALSE);
  415. fResult=FALSE;
  416. goto CommonReturn;
  417. SET_ERROR(NoMatchErr, CRYPT_E_NO_MATCH);
  418. TRACE_ERROR(TraceErr);
  419. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  420. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  421. }
  422. //--------------------------------------------------------------------------
  423. //
  424. // CEPVerifyPasswordAndDeleteFromTable
  425. //
  426. // Need to be protected by the critical section.
  427. //
  428. //--------------------------------------------------------------------------
  429. BOOL WINAPI CEPVerifyPasswordAndDeleteFromTable(LPWSTR pwszPassword, DWORD dwUsage)
  430. {
  431. BOOL fResult=FALSE;
  432. CEP_PASSWORD_ENTRY *pPasswordEntry=NULL;
  433. DWORD dwIndex=0;
  434. EnterCriticalSection(&PasswordCriticalSec);
  435. //delete all expired passwords
  436. CEPPasswordRefresh();
  437. if(NULL == (pPasswordEntry=CEPSearchPassword(pwszPassword, &dwIndex)))
  438. goto InvalidArgErr;
  439. //verify the usage.
  440. //only one signature and one exchange key per password
  441. if(0 != ((pPasswordEntry->dwUsageRequested) & dwUsage))
  442. goto InvalidArgErr;
  443. pPasswordEntry->dwUsageRequested = (pPasswordEntry->dwUsageRequested) | dwUsage;
  444. //remove the password only if both signature and exchange key are requested
  445. if(((pPasswordEntry->dwUsageRequested) & CEP_REQUEST_SIGNATURE) &&
  446. ((pPasswordEntry->dwUsageRequested) & CEP_REQUEST_EXCHANGE))
  447. {
  448. CEPPasswordRemoveValidityEntry(pPasswordEntry->pValidityEntry);
  449. CEPPasswordRemovePasswordEntry(pPasswordEntry, dwIndex);
  450. CEPPasswordFreeValidityEntry(pPasswordEntry->pValidityEntry, FALSE);
  451. CEPPasswordFreePasswordEntry(pPasswordEntry);
  452. if(g_dwPasswordCount >= 1)
  453. g_dwPasswordCount--;
  454. }
  455. fResult=TRUE;
  456. CommonReturn:
  457. LeaveCriticalSection(&PasswordCriticalSec);
  458. return fResult;
  459. ErrorReturn:
  460. fResult=FALSE;
  461. goto CommonReturn;
  462. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  463. }