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.

759 lines
16 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. creden.cpp
  5. Abstract:
  6. This module abstracts user credentials for the multiple credential support.
  7. Author:
  8. Rashmi Patankar (RashmiP) 10-Aug-2001
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include <basetyps.h>
  13. #include <des.h>
  14. typedef long HRESULT;
  15. #include "creden.h"
  16. #include <ntsecapi.h>
  17. typedef NTSTATUS SECURITY_STATUS;
  18. UCHAR g_seed = 0 ;
  19. #define BAIL_ON_FAILURE(hr) \
  20. if (FAILED(hr)) \
  21. { \
  22. goto error; \
  23. }
  24. //
  25. // This routine allocates and stores the password in the
  26. // passed in pointer. The assumption here is that pszString
  27. // is valid, it can be an empty string but not NULL.
  28. // Note that this code cannot be used as is on Win2k and below
  29. // as they do not support the newer functions.
  30. //
  31. HRESULT
  32. EncryptString(
  33. LPWSTR pszString,
  34. LPWSTR *ppszSafeString,
  35. PDWORD pdwLen
  36. )
  37. {
  38. HRESULT hr = S_OK;
  39. DWORD dwLenStr = 0;
  40. DWORD dwPwdLen = 0;
  41. LPWSTR pszTempStr = NULL;
  42. NTSTATUS errStatus = S_OK;
  43. FNRTLINITUNICODESTRING pRtlInitUnicodeString = NULL;
  44. FRTLRUNENCODEUNICODESTRING pRtlRunEncodeUnicodeString = NULL;
  45. FRTLENCRYPTMEMORY pRtlEncryptMemory = NULL;
  46. BOOLEAN GlobalUseScrambling = FALSE;
  47. if (!pszString || !ppszSafeString)
  48. {
  49. return(E_FAIL);
  50. }
  51. *ppszSafeString = NULL;
  52. *pdwLen = 0;
  53. //
  54. // If the string is valid, then we need to get the length
  55. // and initialize the unicode string.
  56. //
  57. UNICODE_STRING Password;
  58. //
  59. // Determine the length of buffer taking padding into account.
  60. //
  61. dwLenStr = wcslen(pszString);
  62. dwPwdLen = (dwLenStr + 1) * sizeof(WCHAR) + (DES_BLOCKLEN -1);
  63. pszTempStr = (LPWSTR) AllocADsMem(dwPwdLen);
  64. if (!pszTempStr)
  65. {
  66. hr = E_OUTOFMEMORY;
  67. goto error;
  68. }
  69. wcscpy(pszTempStr, pszString);
  70. if(g_ScramblingLibraryHandle)
  71. {
  72. pRtlInitUnicodeString = (FNRTLINITUNICODESTRING) GetProcAddress( g_ScramblingLibraryHandle, "RtlInitUnicodeString" );
  73. }
  74. if(!pRtlInitUnicodeString)
  75. {
  76. hr = E_FAIL;
  77. goto error;
  78. }
  79. (*pRtlInitUnicodeString)(&Password, pszTempStr);
  80. USHORT usExtra = 0;
  81. if (usExtra = (Password.MaximumLength % DES_BLOCKLEN))
  82. {
  83. Password.MaximumLength += (DES_BLOCKLEN - usExtra);
  84. }
  85. *pdwLen = Password.MaximumLength;
  86. if (g_AdvApi32LibraryHandle || g_ScramblingLibraryHandle)
  87. {
  88. GlobalUseScrambling = FALSE;
  89. if (g_AdvApi32LibraryHandle)
  90. {
  91. //
  92. // Try to get the advapi32.dll RtlEncryptMemory/RtlDecryptMemory functions,
  93. // Note that RtlEncryptMemory and RtlDecryptMemory are really named
  94. // SystemFunction040/041, hence the macros.
  95. //
  96. pRtlEncryptMemory = (FRTLENCRYPTMEMORY) GetProcAddress( g_AdvApi32LibraryHandle, (LPCSTR) 619 );
  97. if (pRtlEncryptMemory)
  98. {
  99. // We want to use scrambling
  100. GlobalUseScrambling = TRUE;
  101. // Using strong scrambling
  102. errStatus = (*pRtlEncryptMemory)( Password.Buffer,
  103. Password.MaximumLength,
  104. 0
  105. );
  106. if (errStatus)
  107. {
  108. if(pszTempStr)
  109. {
  110. FreeADsMem(pszTempStr);
  111. pszTempStr = NULL;
  112. }
  113. hr = HRESULT_FROM_NT(errStatus);
  114. goto error;
  115. }
  116. }
  117. else if (g_ScramblingLibraryHandle)
  118. {
  119. //
  120. // Clean up so we can try falling back to the run-encode scrambling functions
  121. // (we keep the AdvApi32LibraryHandle around since we'll probably need it
  122. // later anyway)
  123. //
  124. pRtlRunEncodeUnicodeString = (FRTLRUNENCODEUNICODESTRING) GetProcAddress( g_ScramblingLibraryHandle, "RtlRunEncodeUnicodeString" );
  125. if(_tcslen(Password.Buffer) && pRtlRunEncodeUnicodeString)
  126. {
  127. // encrypt password in place
  128. (*pRtlRunEncodeUnicodeString)( &g_seed, &Password );
  129. }
  130. else
  131. {
  132. hr = E_FAIL;
  133. goto error;
  134. }
  135. }
  136. else
  137. {
  138. hr = E_FAIL;
  139. goto error;
  140. }
  141. }
  142. else
  143. {
  144. hr = E_FAIL;
  145. goto error;
  146. }
  147. }
  148. else
  149. {
  150. hr = E_FAIL;
  151. goto error;
  152. }
  153. *ppszSafeString = pszTempStr;
  154. error:
  155. if (FAILED(hr) && pszTempStr)
  156. {
  157. FreeADsMem(pszTempStr);
  158. pszTempStr = NULL;
  159. }
  160. return(hr);
  161. }
  162. HRESULT
  163. DecryptString(
  164. LPWSTR pszEncodedString,
  165. LPWSTR *ppszString,
  166. DWORD dwLen
  167. )
  168. {
  169. HRESULT hr = E_FAIL;
  170. LPWSTR pszTempStr = NULL;
  171. NTSTATUS errStatus;
  172. BOOLEAN GlobalUseScrambling = FALSE;
  173. FNRTLINITUNICODESTRING pRtlInitUnicodeString = NULL;
  174. FRTLRUNDECODEUNICODESTRING pRtlRunDecodeUnicodeString = NULL;
  175. FRTLDECRYPTMEMORY pRtlDecryptMemory = NULL;
  176. UNICODE_STRING UnicodePassword;
  177. if (!dwLen || !ppszString)
  178. {
  179. return(E_FAIL);
  180. }
  181. *ppszString = NULL;
  182. if (dwLen)
  183. {
  184. pszTempStr = (LPWSTR) AllocADsMem(dwLen);
  185. if (!pszTempStr)
  186. {
  187. hr = E_OUTOFMEMORY;
  188. goto error;
  189. }
  190. memcpy(pszTempStr, pszEncodedString, dwLen);
  191. if (g_AdvApi32LibraryHandle || g_ScramblingLibraryHandle)
  192. {
  193. hr = S_OK;
  194. GlobalUseScrambling = FALSE;
  195. if (g_AdvApi32LibraryHandle)
  196. {
  197. //
  198. // Try to get the advapi32.dll RtlEncryptMemory/RtlDecryptMemory functions,
  199. // along with ntdll's RtlInitUnicodeString. Note that RtlEncryptMemory
  200. // and RtlDecryptMemory are really named SystemFunction040/041, hence
  201. // the macros.
  202. //
  203. pRtlDecryptMemory = (FRTLDECRYPTMEMORY) GetProcAddress( g_AdvApi32LibraryHandle, (LPCSTR) 620 );
  204. if (pRtlDecryptMemory)
  205. {
  206. //
  207. // We want to use scrambling
  208. //
  209. GlobalUseScrambling = TRUE;
  210. // Using strong scrambling
  211. errStatus = (*pRtlDecryptMemory)( pszTempStr,
  212. dwLen,
  213. 0
  214. );
  215. if (errStatus)
  216. {
  217. if (NULL != pszTempStr)
  218. {
  219. FreeADsStr(pszTempStr);
  220. pszTempStr = NULL;
  221. }
  222. hr = HRESULT_FROM_NT(errStatus);
  223. goto error;
  224. }
  225. }
  226. else if(g_ScramblingLibraryHandle)
  227. {
  228. //
  229. // Clean up so we can try falling back to the run-encode scrambling functions
  230. // (we keep the AdvApi32LibraryHandle around since we'll probably need it
  231. // later anyway)
  232. //
  233. pRtlRunDecodeUnicodeString = (FRTLRUNDECODEUNICODESTRING) GetProcAddress( g_ScramblingLibraryHandle, "RtlRunDecodeUnicodeString" );
  234. pRtlInitUnicodeString = (FNRTLINITUNICODESTRING) GetProcAddress( g_ScramblingLibraryHandle, "RtlInitUnicodeString" );
  235. if(_tcslen(pszTempStr) && pRtlRunDecodeUnicodeString && pRtlInitUnicodeString)
  236. {
  237. (*pRtlInitUnicodeString)( &UnicodePassword, pszTempStr );
  238. // encrypt password in place
  239. (*pRtlRunDecodeUnicodeString)(g_seed, &UnicodePassword);
  240. }
  241. else
  242. {
  243. hr = E_FAIL;
  244. goto error;
  245. }
  246. }
  247. else
  248. {
  249. hr = E_FAIL;
  250. goto error;
  251. }
  252. }
  253. else
  254. {
  255. hr = E_FAIL;
  256. goto error;
  257. }
  258. }
  259. else
  260. {
  261. hr = E_FAIL;
  262. goto error;
  263. }
  264. *ppszString = pszTempStr;
  265. }
  266. error:
  267. if (FAILED(hr) && (NULL != pszTempStr))
  268. {
  269. FreeADsStr(pszTempStr);
  270. pszTempStr = NULL;
  271. }
  272. return(hr);
  273. }
  274. //
  275. // Static member of the class
  276. //
  277. CCredentials::CCredentials():
  278. _lpszUserName(NULL),
  279. _lpszPassword(NULL),
  280. _dwAuthFlags(0),
  281. _dwPasswordLen(0)
  282. {
  283. }
  284. CCredentials::CCredentials(
  285. LPWSTR lpszUserName,
  286. LPWSTR lpszPassword,
  287. DWORD dwAuthFlags
  288. ):
  289. _lpszUserName(NULL),
  290. _lpszPassword(NULL),
  291. _dwAuthFlags(0),
  292. _dwPasswordLen(0)
  293. {
  294. //
  295. // AjayR 10-04-99 we need a way to bail if the
  296. // alloc's fail. Since it is in the constructor this is
  297. // not very easy to do.
  298. //
  299. if (lpszUserName)
  300. {
  301. _lpszUserName = AllocADsStr(lpszUserName);
  302. }
  303. else
  304. {
  305. _lpszUserName = NULL;
  306. }
  307. if (lpszPassword)
  308. {
  309. //
  310. // The call can fail but we cannot recover from this.
  311. //
  312. EncryptString(
  313. lpszPassword,
  314. &_lpszPassword,
  315. &_dwPasswordLen
  316. );
  317. }
  318. else
  319. {
  320. _lpszPassword = NULL;
  321. }
  322. _dwAuthFlags = dwAuthFlags;
  323. }
  324. CCredentials::~CCredentials()
  325. {
  326. if (_lpszUserName)
  327. {
  328. FreeADsStr(_lpszUserName);
  329. }
  330. if (_lpszPassword)
  331. {
  332. FreeADsStr(_lpszPassword);
  333. }
  334. }
  335. HRESULT
  336. CCredentials::GetUserName(
  337. LPWSTR *lppszUserName
  338. )
  339. {
  340. if (!lppszUserName)
  341. {
  342. return(E_FAIL);
  343. }
  344. if (!_lpszUserName)
  345. {
  346. *lppszUserName = NULL;
  347. }
  348. else
  349. {
  350. *lppszUserName = AllocADsStr(_lpszUserName);
  351. if (!*lppszUserName)
  352. {
  353. return(E_OUTOFMEMORY);
  354. }
  355. }
  356. return(S_OK);
  357. }
  358. HRESULT
  359. CCredentials::GetPassword(
  360. LPWSTR * lppszPassword
  361. )
  362. {
  363. if (!lppszPassword)
  364. {
  365. return(E_FAIL);
  366. }
  367. if (!_lpszPassword)
  368. {
  369. *lppszPassword = NULL;
  370. }
  371. else
  372. {
  373. return( DecryptString( _lpszPassword,
  374. lppszPassword,
  375. _dwPasswordLen
  376. )
  377. );
  378. }
  379. return(S_OK);
  380. }
  381. HRESULT
  382. CCredentials::SetUserName(
  383. LPWSTR lpszUserName
  384. )
  385. {
  386. if (_lpszUserName)
  387. {
  388. FreeADsStr(_lpszUserName);
  389. }
  390. if (!lpszUserName)
  391. {
  392. _lpszUserName = NULL;
  393. return(S_OK);
  394. }
  395. _lpszUserName = AllocADsStr(
  396. lpszUserName
  397. );
  398. if(!_lpszUserName)
  399. {
  400. return(E_FAIL);
  401. }
  402. return(S_OK);
  403. }
  404. HRESULT
  405. CCredentials::SetPassword(
  406. LPWSTR lpszPassword
  407. )
  408. {
  409. if (_lpszPassword)
  410. {
  411. FreeADsStr(_lpszPassword);
  412. }
  413. if (!lpszPassword)
  414. {
  415. _lpszPassword = NULL;
  416. return(S_OK);
  417. }
  418. return( EncryptString( lpszPassword,
  419. &_lpszPassword,
  420. &_dwPasswordLen
  421. )
  422. );
  423. }
  424. CCredentials::CCredentials(
  425. const CCredentials& Credentials
  426. )
  427. {
  428. HRESULT hr = S_OK;
  429. LPWSTR pszTmpPwd = NULL;
  430. _lpszUserName = NULL;
  431. _lpszPassword = NULL;
  432. _lpszUserName = AllocADsStr(
  433. Credentials._lpszUserName
  434. );
  435. if (Credentials._lpszPassword)
  436. {
  437. hr = DecryptString(
  438. Credentials._lpszPassword,
  439. &pszTmpPwd,
  440. Credentials._dwPasswordLen
  441. );
  442. }
  443. if (SUCCEEDED(hr) && pszTmpPwd)
  444. {
  445. hr = EncryptString(
  446. pszTmpPwd,
  447. &_lpszPassword,
  448. &_dwPasswordLen
  449. );
  450. }
  451. else
  452. {
  453. pszTmpPwd = NULL;
  454. }
  455. if (pszTmpPwd)
  456. {
  457. FreeADsStr(pszTmpPwd);
  458. }
  459. _dwAuthFlags = Credentials._dwAuthFlags;
  460. }
  461. void
  462. CCredentials::operator=(
  463. const CCredentials& other
  464. )
  465. {
  466. HRESULT hr = S_OK;
  467. LPWSTR pszTmpPwd = NULL;
  468. if ( &other == this)
  469. {
  470. return;
  471. }
  472. if (_lpszUserName)
  473. {
  474. FreeADsStr(_lpszUserName);
  475. }
  476. if (_lpszPassword)
  477. {
  478. FreeADsStr(_lpszPassword);
  479. }
  480. _lpszUserName = AllocADsStr(
  481. other._lpszUserName
  482. );
  483. if (other._lpszPassword)
  484. {
  485. hr = DecryptString(
  486. other._lpszPassword,
  487. &pszTmpPwd,
  488. other._dwPasswordLen
  489. );
  490. }
  491. if (SUCCEEDED(hr) && pszTmpPwd)
  492. {
  493. hr = EncryptString(
  494. pszTmpPwd,
  495. &_lpszPassword,
  496. &_dwPasswordLen
  497. );
  498. }
  499. else
  500. {
  501. pszTmpPwd = NULL;
  502. }
  503. if (pszTmpPwd)
  504. {
  505. FreeADsStr(pszTmpPwd);
  506. }
  507. _dwAuthFlags = other._dwAuthFlags;
  508. return;
  509. }
  510. BOOL
  511. operator==(
  512. CCredentials& x,
  513. CCredentials& y
  514. )
  515. {
  516. BOOL bEqualUser = FALSE;
  517. BOOL bEqualPassword = FALSE;
  518. BOOL bEqualFlags = FALSE;
  519. LPWSTR lpszXPassword = NULL;
  520. LPWSTR lpszYPassword = NULL;
  521. BOOL bReturnCode = FALSE;
  522. HRESULT hr = S_OK;
  523. if (x._lpszUserName && y._lpszUserName)
  524. {
  525. bEqualUser = !(wcscmp(x._lpszUserName, y._lpszUserName));
  526. }
  527. else if (!x._lpszUserName && !y._lpszUserName)
  528. {
  529. bEqualUser = TRUE;
  530. }
  531. hr = x.GetPassword(&lpszXPassword);
  532. if (FAILED(hr))
  533. {
  534. goto error;
  535. }
  536. hr = y.GetPassword(&lpszYPassword);
  537. if (FAILED(hr))
  538. {
  539. goto error;
  540. }
  541. if ((lpszXPassword && lpszYPassword))
  542. {
  543. bEqualPassword = !(wcscmp(lpszXPassword, lpszYPassword));
  544. }
  545. else if (!lpszXPassword && !lpszYPassword)
  546. {
  547. bEqualPassword = TRUE;
  548. }
  549. if (x._dwAuthFlags == y._dwAuthFlags)
  550. {
  551. bEqualFlags = TRUE;
  552. }
  553. if (bEqualUser && bEqualPassword && bEqualFlags)
  554. {
  555. bReturnCode = TRUE;
  556. }
  557. error:
  558. if (lpszXPassword)
  559. {
  560. FreeADsStr(lpszXPassword);
  561. }
  562. if (lpszYPassword)
  563. {
  564. FreeADsStr(lpszYPassword);
  565. }
  566. return(bReturnCode);
  567. }
  568. BOOL
  569. CCredentials::IsNullCredentials(
  570. )
  571. {
  572. // The function will return true even if the flags are set
  573. // this is because we want to try and get the default credentials
  574. // even if the flags were set
  575. if (!_lpszUserName && !_lpszPassword)
  576. {
  577. return(TRUE);
  578. }
  579. else
  580. {
  581. return(FALSE);
  582. }
  583. }
  584. DWORD
  585. CCredentials::GetAuthFlags()
  586. {
  587. return(_dwAuthFlags);
  588. }
  589. void
  590. CCredentials::SetAuthFlags(
  591. DWORD dwAuthFlags
  592. )
  593. {
  594. _dwAuthFlags = dwAuthFlags;
  595. }