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.

531 lines
14 KiB

  1. #include <pch.cpp>
  2. #pragma hdrstop
  3. #define MAX_PW_LEN 160
  4. #define MAX_STRING_RSC_SIZE 512
  5. #define WSZ_NULLSTRING L""
  6. extern HINSTANCE g_hInst;
  7. extern "C" {
  8. typedef DWORD (WINAPI *WNETGETUSERA)(
  9. LPCSTR lpName,
  10. LPSTR lpUserName,
  11. LPDWORD lpnLength
  12. );
  13. extern WNETGETUSERA _WNetGetUserA;
  14. }
  15. typedef struct _GETWINPW_DIALOGARGS
  16. {
  17. LPWSTR* ppszPW;
  18. PST_PROVIDER_HANDLE *phPSTProv;
  19. } GETWINPW_DIALOGARGS, *PGETWINPW_DIALOGARGS;
  20. INT_PTR CALLBACK DialogGetWindowsPassword(
  21. HWND hDlg, // handle to dialog box
  22. UINT message, // message
  23. WPARAM wParam, // first message parameter
  24. LPARAM lParam // second message parameter
  25. )
  26. {
  27. int iRet = IDCANCEL; // assume cancel
  28. BOOL bSuccess = FALSE; // assume error
  29. WCHAR szMessage[MAX_STRING_RSC_SIZE];
  30. WCHAR szDlgTitle[MAX_STRING_RSC_SIZE];
  31. switch (message)
  32. {
  33. case WM_INITDIALOG:
  34. {
  35. UINT uResString;
  36. SetLastError( 0 ); // as per win32 documentation
  37. if(SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)lParam) == 0) {
  38. if(GetLastError() != ERROR_SUCCESS) {
  39. EndDialog(hDlg, IDCANCEL);
  40. return FALSE;
  41. }
  42. }
  43. if(FIsWinNT()) {
  44. uResString = IDS_GET_WINDOWS_PASSWORD_NT;
  45. } else {
  46. uResString = IDS_GET_WINDOWS_PASSWORD_95;
  47. }
  48. LoadStringU(
  49. g_hInst,
  50. uResString,
  51. szMessage,
  52. MAX_STRING_RSC_SIZE);
  53. SetWindowTextU(GetDlgItem(hDlg, IDC_MESSAGE), szMessage);
  54. return TRUE;
  55. }
  56. case WM_COMMAND:
  57. if (LOWORD(wParam) == IDOK)
  58. {
  59. PGETWINPW_DIALOGARGS pDlgArgs;
  60. LPWSTR* ppszPW;
  61. WCHAR sz1[MAX_PW_LEN];
  62. DWORD cch1 = 0;
  63. BOOL bPasswordVerified;
  64. pDlgArgs = (PGETWINPW_DIALOGARGS)GetWindowLongPtr(hDlg, GWLP_USERDATA);
  65. if(pDlgArgs == 0) break; // TODO: bail out
  66. ppszPW = pDlgArgs->ppszPW;
  67. *ppszPW = NULL;
  68. // must impersonate client. If it fails, bail.
  69. if(!FImpersonateClient(pDlgArgs->phPSTProv))
  70. break;
  71. cch1 = GetDlgItemTextU(
  72. hDlg,
  73. IDC_EDIT1,
  74. sz1,
  75. MAX_PW_LEN);
  76. // push an hourglass to the screen
  77. HCURSOR curOld;
  78. curOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  79. // validate password
  80. bPasswordVerified = VerifyWindowsPassword(sz1);
  81. // put old cursor back
  82. SetCursor(curOld);
  83. FRevertToSelf(pDlgArgs->phPSTProv);
  84. // Clear any queued user keyboard entry turds before returning
  85. MSG sMsg;
  86. while (PeekMessage(&sMsg, hDlg, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
  87. ;
  88. if(!bPasswordVerified)
  89. {
  90. szMessage[0] = L'\0';
  91. LoadStringU(
  92. g_hInst,
  93. IDS_PASSWORD_NOVERIFY,
  94. szMessage,
  95. MAX_STRING_RSC_SIZE);
  96. szDlgTitle[0] = L'\0';
  97. LoadStringU(
  98. g_hInst,
  99. IDS_PASSWORD_ERROR_DLGTITLE,
  100. szDlgTitle,
  101. MAX_STRING_RSC_SIZE);
  102. // this W implemented in both Win95 & NT!
  103. MessageBoxW(
  104. NULL, // hDlg,
  105. szMessage,
  106. szDlgTitle,
  107. MB_OK|MB_ICONEXCLAMATION|MB_SERVICE_NOTIFICATION);
  108. SetWindowTextU(GetDlgItem(hDlg, IDC_EDIT1), WSZ_NULLSTRING);
  109. goto cleanup;
  110. }
  111. // now bite it: save
  112. SS_ASSERT(ppszPW != NULL);
  113. *ppszPW = (LPWSTR)SSAlloc( (cch1+1) * sizeof(WCHAR) );
  114. if(*ppszPW == NULL) goto cleanup;
  115. //
  116. // sfield: defer copying strings until we know everything succeeded.
  117. // this way, we don't have to zero these buffers if some
  118. // allocs + copies succeed, and others fail.
  119. //
  120. wcscpy(*ppszPW, sz1);
  121. iRet = IDOK;
  122. bSuccess = TRUE;
  123. cleanup:
  124. if(cch1) RtlSecureZeroMemory(sz1, cch1 * sizeof(WCHAR));
  125. if(!bSuccess)
  126. {
  127. if(*ppszPW)
  128. {
  129. SSFree(*ppszPW);
  130. *ppszPW = NULL;
  131. }
  132. return FALSE;
  133. }
  134. break; // things went OK, just bail to EndDialog
  135. } // IDOK
  136. if( LOWORD(wParam) == IDCANCEL )
  137. break;
  138. default:
  139. return FALSE;
  140. }
  141. EndDialog(hDlg, iRet);
  142. return bSuccess;
  143. }
  144. BOOL
  145. FGetWindowsPassword(
  146. IN PST_PROVIDER_HANDLE *hPSTProv,
  147. IN BYTE rgbPasswordDerivedBytes[],
  148. IN DWORD cbPasswordDerivedBytes
  149. )
  150. {
  151. BOOL fRet;
  152. LPWSTR pszPW = NULL;
  153. if ((rgbPasswordDerivedBytes == NULL) || (cbPasswordDerivedBytes < A_SHA_DIGEST_LEN))
  154. return FALSE;
  155. //
  156. // the general event flow for this routine:
  157. //
  158. // 1. Search cache for credentials. WinNT requires impersonating around search.
  159. // 2. If search fails on Win95, try to get the password directly from MPR
  160. // 3. If search fails on WinNT, check for special cases like LocalSystem and NETWORK
  161. // Allow Local System by building fixed credential.
  162. // Disallow NETWORK because no credentials exist (return FAILURE).
  163. // 4. If we still don't have credentials, prompt user via UI.
  164. //
  165. //
  166. // we must be impersonating around this call !!!
  167. //
  168. if(!FImpersonateClient(hPSTProv))
  169. return FALSE;
  170. fRet = GetPasswordNT(rgbPasswordDerivedBytes);
  171. FRevertToSelf(hPSTProv);
  172. // if either GetPassword routine fails
  173. if (!fRet)
  174. {
  175. INT_PTR iRet;
  176. DWORD cbPassword;
  177. BOOL fCachePassword = TRUE; // cache the results by default
  178. BOOL fSpecialCase;
  179. if(!FImpersonateClient(hPSTProv))
  180. goto Ret;
  181. //
  182. // WinNT: check for some special cases, namely, if we are runninng
  183. // under Local System or Network credentials.
  184. //
  185. fRet = GetSpecialCasePasswordNT(
  186. rgbPasswordDerivedBytes, // derived bits when fSpecialCase == TRUE
  187. &fSpecialCase // legal special case encountered?
  188. );
  189. FRevertToSelf(hPSTProv);
  190. //
  191. // if the query failed bail out, since we encountered an illegal
  192. // or inapproriate condition.
  193. //
  194. if(!fRet)
  195. goto Ret;
  196. //
  197. // now, set fRet to the result of the special case test.
  198. // so, if we encountered an allowed special case, we have an
  199. // validly filled rgbPasswordDerivedBytes buffer. If we didn't
  200. // encounter a legal special case, we continue on our quest for
  201. // a password.
  202. //
  203. fRet = fSpecialCase;
  204. //
  205. // re-evaluate fRet for the special hack for Win95 above.
  206. //
  207. if(!fRet) {
  208. // return a validated password
  209. GETWINPW_DIALOGARGS DialogArgs = {&pszPW, hPSTProv};
  210. iRet = DialogBoxParam(
  211. g_hInst,
  212. MAKEINTRESOURCE(IDD_GET_WINDOWS_PASSWORD),
  213. NULL,
  214. DialogGetWindowsPassword,
  215. (LPARAM)&DialogArgs);
  216. if(iRet != IDOK) goto Ret;
  217. if (pszPW == NULL)
  218. goto Ret;
  219. //
  220. // everything went fine, now derive the password bits!
  221. //
  222. cbPassword = WSZ_BYTECOUNT(pszPW) - sizeof(WCHAR) ;
  223. // hash pwd, copy out
  224. A_SHA_CTX sSHAHash;
  225. A_SHAInit(&sSHAHash);
  226. A_SHAUpdate(&sSHAHash, (BYTE *) pszPW, cbPassword);
  227. RtlSecureZeroMemory(pszPW, cbPassword); // sfield: zero the password
  228. // Finish off the hash
  229. A_SHAFinal(&sSHAHash, rgbPasswordDerivedBytes);
  230. }
  231. //
  232. // now, update the password cache
  233. //
  234. if(fCachePassword)
  235. {
  236. LUID AuthenticationId;
  237. // get user LUID
  238. //
  239. // we must be impersonating around this call !!!
  240. //
  241. if(!FImpersonateClient(hPSTProv))
  242. goto Ret;
  243. if(!GetThreadAuthenticationId(
  244. GetCurrentThread(),
  245. &AuthenticationId))
  246. {
  247. FRevertToSelf(hPSTProv);
  248. goto Ret;
  249. }
  250. if (!SetPasswordNT(
  251. &AuthenticationId,
  252. rgbPasswordDerivedBytes))
  253. {
  254. FRevertToSelf(hPSTProv);
  255. goto Ret;
  256. }
  257. FRevertToSelf(hPSTProv);
  258. } // fCachePassword
  259. }
  260. fRet = TRUE;
  261. Ret:
  262. if (pszPW)
  263. SSFree(pszPW);
  264. return fRet;
  265. }
  266. BOOL
  267. FIsACLSatisfied(
  268. IN PST_PROVIDER_HANDLE *hPSTProv,
  269. IN PST_ACCESSRULESET *psRules,
  270. IN DWORD dwAccess,
  271. IN OUT LPVOID // coming soon: fill a status structure with data about access attempt
  272. )
  273. {
  274. if ((psRules->cRules == 0)||(psRules->rgRules == NULL))
  275. return TRUE;
  276. //
  277. // parent exe name. cached through loop
  278. //
  279. LPWSTR pszParentExeName = NULL;
  280. //
  281. // direct caller image. cached through loop
  282. //
  283. LPWSTR pszDirectCaller = NULL;
  284. //
  285. // base address of direct call module
  286. //
  287. DWORD_PTR BaseAddressDirect;
  288. //
  289. // module that is the subject of analysis
  290. //
  291. LPWSTR szHashTarget;
  292. //
  293. // search for a list of terms that are completely satisfied
  294. //
  295. for(DWORD cRule=0; cRule<psRules->cRules; cRule++)
  296. {
  297. // check only those rules that govern the right access
  298. //
  299. // loop while we still have dwAccess modes to check
  300. //
  301. if (0 == (psRules->rgRules[cRule].AccessModeFlags & dwAccess))
  302. continue;
  303. // evaluate the ith term
  304. PPST_ACCESSCLAUSE pClause;
  305. // walk down list
  306. for(DWORD cClause=0; cClause<psRules->rgRules[cRule].cClauses; cClause++)
  307. {
  308. pClause = &psRules->rgRules[cRule].rgClauses[cClause];
  309. // for each term, make sure ALL ENTRIES are satisfied
  310. // TODO: what to do if clause data not self relative?
  311. // not possible at this point in time, but it may come up later
  312. //
  313. switch(pClause->ClauseType & ~PST_SELF_RELATIVE_CLAUSE)
  314. {
  315. // for each type, may use the pClause->pbClauseData
  316. case PST_SECURITY_DESCRIPTOR:
  317. {
  318. // passed test
  319. continue; // next clause
  320. }
  321. case PST_AUTHENTICODE:
  322. {
  323. // passed test
  324. continue; // next clause
  325. }
  326. case PST_BINARY_CHECK:
  327. {
  328. // passed test
  329. continue; // next clause
  330. }
  331. default:
  332. // unknown type in ACL: this chain failed, goto next chain
  333. goto NextRule; // next rule
  334. }
  335. }
  336. // YES! ALL clauses evaluated and OK
  337. // turn off the bits that got us into this clause chain
  338. dwAccess &= ~ psRules->rgRules[cRule].AccessModeFlags;
  339. NextRule:
  340. continue;
  341. }
  342. //Cleanup:
  343. // cleanup
  344. if (pszParentExeName)
  345. SSFree(pszParentExeName);
  346. if(pszDirectCaller)
  347. SSFree(pszDirectCaller);
  348. return (dwAccess == 0);
  349. }
  350. BOOL FGetUser(
  351. PST_PROVIDER_HANDLE *hPSTProv,
  352. LPWSTR* ppszUser)
  353. {
  354. return FGetUserName(hPSTProv, ppszUser);
  355. }
  356. BOOL
  357. FGetCallerName(
  358. IN PST_PROVIDER_HANDLE *hPSTProv,
  359. OUT LPWSTR* ppszCallerName,
  360. OUT DWORD_PTR *lpdwBaseAddress
  361. )
  362. {
  363. return FGetParentFileName(hPSTProv, ppszCallerName, lpdwBaseAddress);
  364. }
  365. BOOL
  366. FGetServerParam(
  367. IN PST_PROVIDER_HANDLE *hPSTProv,
  368. IN DWORD dwParam,
  369. IN LPVOID pData,
  370. IN OUT DWORD *pcbData
  371. )
  372. {
  373. //
  374. // check for the server get param that asks for private dispatch interfaces
  375. //
  376. if( dwParam == SS_SERVERPARAM_CALLBACKS &&
  377. *pcbData >= sizeof( PRIVATE_CALLBACKS )) {
  378. PRIVATE_CALLBACKS *PrivateCallbacks = (PRIVATE_CALLBACKS *)pData;
  379. PrivateCallbacks->cbSize = sizeof( PRIVATE_CALLBACKS );
  380. PrivateCallbacks->pfnFGetWindowsPassword = FGetWindowsPassword;
  381. PrivateCallbacks->pfnAuthenticodeInitPolicy = NULL;
  382. PrivateCallbacks->pfnAuthenticodeFinalPolicy = NULL;
  383. *pcbData = sizeof( PRIVATE_CALLBACKS );
  384. return TRUE;
  385. }
  386. SetLastError(ERROR_INVALID_PARAMETER);
  387. return FALSE;
  388. }
  389. BOOL
  390. FSetServerParam(
  391. IN PST_PROVIDER_HANDLE *hPSTProv,
  392. IN DWORD dwParam,
  393. IN LPVOID pData,
  394. IN DWORD pcbData
  395. )
  396. {
  397. SetLastError(ERROR_INVALID_PARAMETER);
  398. return FALSE;
  399. }