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.

478 lines
12 KiB

  1. /******************************************************************************\
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. reclient.c
  5. Abstract:
  6. Implements access to the DW creation pipe.
  7. Revision History:
  8. created derekm 10/15/00
  9. \******************************************************************************/
  10. #include "precomp.h"
  11. #include <pchrexec.h>
  12. static CONST WCHAR wszHangPipe[] = ERRORREP_HANG_PIPENAME;
  13. BOOL MyCallNamedPipe(
  14. LPCWSTR wszPipe,
  15. LPVOID pvIn,
  16. DWORD cbIn,
  17. LPVOID pvOut,
  18. DWORD cbOut,
  19. DWORD *pcbRead,
  20. DWORD dwWaitPipe,
  21. DWORD dwWaitRead)
  22. {
  23. HRESULT hr = NOERROR;
  24. HANDLE hPipe = INVALID_HANDLE_VALUE;
  25. HANDLE hev = NULL;
  26. DWORD dwStart = GetTickCount(), dwNow, dw;
  27. BOOL fRet = FALSE;
  28. OVERLAPPED ol;
  29. DWORD dwMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
  30. DWORD cbRead = 0;
  31. UserAssert(wszPipe != NULL);
  32. UserAssert(pvIn != NULL);
  33. UserAssert(pvOut != NULL);
  34. UserAssert(pcbRead != NULL);
  35. *pcbRead = 0;
  36. for(;;) {
  37. hPipe = CreateFileW(wszPipe, GENERIC_READ | GENERIC_WRITE,
  38. FILE_SHARE_READ | FILE_SHARE_WRITE,
  39. NULL, OPEN_EXISTING,
  40. FILE_FLAG_OVERLAPPED | SECURITY_IDENTIFICATION |
  41. SECURITY_SQOS_PRESENT | SECURITY_CONTEXT_TRACKING,
  42. NULL);
  43. if (hPipe != INVALID_HANDLE_VALUE) {
  44. break;
  45. }
  46. fRet = WaitNamedPipeW(wszPipe, dwWaitPipe);
  47. if (!fRet) {
  48. goto done;
  49. }
  50. dwNow = GetTickCount();
  51. if (dwNow < dwStart) {
  52. dw = ((DWORD)-1 - dwStart) + dwNow;
  53. } else {
  54. dw = dwNow - dwStart;
  55. }
  56. if (dw >= dwWaitPipe) {
  57. dwWaitPipe = 0;
  58. } else {
  59. dwWaitPipe -= dw;
  60. }
  61. }
  62. // Default open is readmode byte stream- change to message mode.
  63. fRet = SetNamedPipeHandleState(hPipe, &dwMode, NULL, NULL);
  64. if (!fRet) {
  65. goto done;
  66. }
  67. // we need an event for the overlapped structure
  68. hev = CreateEventW(NULL, TRUE, FALSE, NULL);
  69. if (hev == NULL) {
  70. fRet = FALSE;
  71. goto done;
  72. }
  73. // populate the overlapped stuff
  74. ZeroMemory(&ol, sizeof(ol));
  75. ol.hEvent = hev;
  76. if (GetSystemMetrics(SM_SHUTTINGDOWN)) {
  77. SetLastError(WAIT_TIMEOUT);
  78. fRet = FALSE;
  79. goto done;
  80. }
  81. fRet = TransactNamedPipe(hPipe, pvIn, cbIn, pvOut, cbOut, &cbRead, &ol);
  82. if (GetLastError() != ERROR_IO_PENDING) {
  83. if (fRet) {
  84. SetEvent(hev);
  85. } else {
  86. goto done;
  87. }
  88. }
  89. dw = WaitForSingleObject(hev, dwWaitRead);
  90. if (dw != WAIT_OBJECT_0) {
  91. if (dw == WAIT_TIMEOUT) {
  92. SetLastError(WAIT_TIMEOUT);
  93. fRet = FALSE;
  94. }
  95. goto done;
  96. }
  97. fRet = GetOverlappedResult(hPipe, &ol, &cbRead, FALSE);
  98. if (fRet == FALSE) {
  99. goto done;
  100. }
  101. *pcbRead = cbRead;
  102. hr = NOERROR;
  103. done:
  104. if (hPipe != INVALID_HANDLE_VALUE) {
  105. CloseHandle(hPipe);
  106. }
  107. if (hev != NULL) {
  108. CloseHandle(hev);
  109. }
  110. return fRet;
  111. }
  112. // ***************************************************************************
  113. LPWSTR MarshallString(
  114. LPWSTR wszSrc,
  115. PBYTE pBase,
  116. ULONG cbMaxBuf,
  117. PBYTE *ppToWrite,
  118. DWORD *pcbWritten)
  119. {
  120. DWORD cb;
  121. PBYTE pwszNormalized;
  122. cb = (wcslen(wszSrc) + 1) * sizeof(WCHAR);
  123. if ((*pcbWritten + cb) > cbMaxBuf) {
  124. return NULL;
  125. }
  126. RtlMoveMemory(*ppToWrite, wszSrc, cb);
  127. // the normalized ptr is the current count
  128. pwszNormalized = (PBYTE)(*ppToWrite - pBase);
  129. // cb is always a mutliple of sizeof(WHCAR) so the pointer addition below
  130. // always produces a result that is 2byte aligned (assuming the input was
  131. // 2byte aligned of course)
  132. *ppToWrite += cb;
  133. *pcbWritten += cb;
  134. return (LPWSTR)pwszNormalized;
  135. }
  136. BOOL StartHangReport(
  137. ULONG ulSessionId,
  138. LPWSTR wszEventName,
  139. DWORD dwpidHung,
  140. DWORD dwtidHung,
  141. BOOL f64Bit,
  142. HANDLE *phProcDumprep)
  143. {
  144. SPCHExecServHangRequest *pesreq;
  145. SPCHExecServHangReply esrep;
  146. DWORD cbRead, cbReq;
  147. CONST WCHAR *pwszPipeName = wszHangPipe;
  148. LPBYTE pBuffer, pBuf;
  149. BOOL fRet = FALSE;
  150. /*
  151. * Validate params.
  152. */
  153. UserAssert(wszEventName);
  154. UserAssert(phProcDumprep != NULL);
  155. UserAssert(dwpidHung != 0 && dwtidHung != 0);
  156. *phProcDumprep = NULL;
  157. /*
  158. * Setup the marshalling - make sure that pBuf is aligned on a 2byte
  159. * boundary beacause we'll be writing WCHAR buffers to it.
  160. */
  161. pBuffer = LocalAlloc(LPTR, ERRORREP_PIPE_BUF_SIZE);
  162. if (pBuffer == NULL) {
  163. goto done;
  164. }
  165. pesreq = (SPCHExecServHangRequest *)pBuffer;
  166. cbReq = sizeof(SPCHExecServHangRequest) +
  167. (sizeof(WCHAR) -
  168. (sizeof(SPCHExecServHangRequest) % sizeof(WCHAR)));
  169. pBuf = pBuffer + cbReq;
  170. // set the basic parameters
  171. pesreq->cbESR = sizeof(SPCHExecServHangRequest);
  172. pesreq->pidReqProcess = GetCurrentProcessId();
  173. pesreq->ulSessionId = ulSessionId;
  174. pesreq->dwpidHung = dwpidHung;
  175. pesreq->dwtidHung = dwtidHung;
  176. pesreq->fIs64bit = f64Bit;
  177. // marshall all the strings we send across the wire.
  178. pesreq->wszEventName = (UINT64)MarshallString(wszEventName,
  179. pBuffer,
  180. ERRORREP_PIPE_BUF_SIZE,
  181. &pBuf,
  182. &cbReq);
  183. if (pesreq->wszEventName == 0) {
  184. goto done;
  185. }
  186. // set the total size of the message
  187. pesreq->cbTotal = cbReq;
  188. if (GetSystemMetrics(SM_SHUTTINGDOWN)) {
  189. SetLastError(WAIT_TIMEOUT);
  190. fRet = FALSE;
  191. goto done;
  192. }
  193. /*
  194. * Send the buffer out to the server - wait at most 2m for this to
  195. * succeed. If it times out, bail.
  196. */
  197. fRet = MyCallNamedPipe(pwszPipeName,
  198. pBuffer,
  199. cbReq,
  200. &esrep,
  201. sizeof(esrep),
  202. &cbRead,
  203. 120000,
  204. 120000);
  205. if (fRet == FALSE) {
  206. goto done;
  207. }
  208. // Check the result
  209. fRet = (esrep.ess == essOk);
  210. if (fRet == FALSE) {
  211. SetLastError(esrep.dwErr);
  212. goto done;
  213. }
  214. *phProcDumprep = esrep.hProcess;
  215. done:
  216. if (pBuffer != NULL) {
  217. LocalFree(pBuffer);
  218. }
  219. return fRet;
  220. }
  221. // ***************************************************************************
  222. NTSTATUS AllocDefSD(
  223. SECURITY_DESCRIPTOR *psd,
  224. DWORD dwOALS,
  225. DWORD dwWA)
  226. {
  227. SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY;
  228. SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY;
  229. PTOKEN_USER ptu = NULL;
  230. NTSTATUS Status;
  231. HANDLE hToken = NULL;
  232. DWORD cb, cbGot;
  233. PACL pacl = NULL;
  234. PSID psidOwner = NULL;
  235. PSID psidLS = NULL;
  236. PSID psidWorld = NULL;
  237. PSID psidAnon = NULL;
  238. UserAssert(psd != NULL);
  239. Status = RtlCreateSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION);
  240. if (!NT_SUCCESS(Status)) {
  241. goto done;
  242. }
  243. // get the SID for the creator / owner
  244. Status = NtOpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hToken);
  245. if (Status == STATUS_NO_TOKEN) {
  246. Status = NtOpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken);
  247. }
  248. if (!NT_SUCCESS(Status)) {
  249. goto done;
  250. }
  251. Status = NtQueryInformationToken(hToken, TokenUser, NULL, 0, &cb);
  252. if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) {
  253. goto done;
  254. }
  255. ptu = LocalAlloc(LPTR, cb);
  256. if (ptu == NULL) {
  257. Status = STATUS_NO_MEMORY;
  258. goto done;
  259. }
  260. Status = NtQueryInformationToken(hToken, TokenUser, (LPVOID)ptu, cb, &cbGot);
  261. if (!NT_SUCCESS(Status)) {
  262. goto done;
  263. }
  264. // make a copy of the owner SID so we can use it in the owner & group field
  265. cb = RtlLengthSid(ptu->User.Sid);
  266. psidOwner = (PSID)LocalAlloc(LMEM_FIXED, cb);
  267. if (psidOwner == NULL) {
  268. Status = STATUS_NO_MEMORY;
  269. goto done;
  270. }
  271. Status = RtlCopySid(cb, psidOwner, ptu->User.Sid);
  272. if (!NT_SUCCESS(Status)) {
  273. goto done;
  274. }
  275. // get the SID for local system acct
  276. Status = RtlAllocateAndInitializeSid(&siaNT,
  277. 1,
  278. SECURITY_LOCAL_SYSTEM_RID,
  279. 0, 0, 0, 0, 0, 0, 0,
  280. &psidLS);
  281. if (!NT_SUCCESS(Status)) {
  282. goto done;
  283. }
  284. cb = sizeof(ACL) + RtlLengthSid(psidLS) + RtlLengthSid(psidOwner) +
  285. 2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD));
  286. if (dwWA != 0) {
  287. // get the SID for the world (everyone)
  288. Status = RtlAllocateAndInitializeSid(&siaNT,
  289. 1,
  290. SECURITY_ANONYMOUS_LOGON_RID,
  291. 0, 0, 0, 0, 0, 0, 0,
  292. &psidWorld);
  293. // get the SID for the anonymous users acct
  294. Status = RtlAllocateAndInitializeSid(&siaWorld,
  295. 1,
  296. SECURITY_WORLD_RID,
  297. 0, 0, 0, 0, 0, 0, 0,
  298. &psidAnon);
  299. if (!NT_SUCCESS(Status)) {
  300. goto done;
  301. }
  302. cb += RtlLengthSid(psidWorld) + RtlLengthSid(psidAnon) +
  303. 2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD));
  304. }
  305. // make the DACL
  306. pacl = (PACL)LocalAlloc(LMEM_FIXED, cb);
  307. if (pacl == NULL) {
  308. Status = STATUS_NO_MEMORY;
  309. goto done;
  310. }
  311. Status = RtlCreateAcl(pacl, cb, ACL_REVISION);
  312. if (!NT_SUCCESS(Status)) {
  313. goto done;
  314. }
  315. Status = RtlAddAccessAllowedAce(pacl, ACL_REVISION, dwOALS, psidOwner);
  316. if (!NT_SUCCESS(Status)) {
  317. goto done;
  318. }
  319. Status = RtlAddAccessAllowedAce(pacl, ACL_REVISION, dwOALS, psidLS);
  320. if (!NT_SUCCESS(Status)) {
  321. goto done;
  322. }
  323. if (dwWA != 0) {
  324. Status = RtlAddAccessAllowedAce(pacl, ACL_REVISION, dwWA, psidWorld);
  325. if (!NT_SUCCESS(Status)) {
  326. goto done;
  327. }
  328. Status = RtlAddAccessAllowedAce(pacl, ACL_REVISION, dwWA, psidAnon);
  329. if (!NT_SUCCESS(Status)) {
  330. goto done;
  331. }
  332. }
  333. // set the SD owner
  334. Status = RtlSetOwnerSecurityDescriptor(psd, psidOwner, TRUE);
  335. if (!NT_SUCCESS(Status)) {
  336. goto done;
  337. }
  338. // set the SD group
  339. Status = RtlSetGroupSecurityDescriptor(psd, psidOwner, FALSE);
  340. if (!NT_SUCCESS(Status)) {
  341. goto done;
  342. }
  343. // set the SD dacl
  344. Status = RtlSetDaclSecurityDescriptor(psd, TRUE, pacl, FALSE);
  345. if (!NT_SUCCESS(Status)) {
  346. goto done;
  347. }
  348. psidOwner = NULL;
  349. pacl = NULL;
  350. done:
  351. if (hToken != NULL) {
  352. CloseHandle(hToken);
  353. }
  354. if (psidLS != NULL) {
  355. RtlFreeSid(psidLS);
  356. }
  357. if (psidWorld != NULL) {
  358. RtlFreeSid(psidWorld);
  359. }
  360. if (psidAnon != NULL) {
  361. RtlFreeSid(psidAnon);
  362. }
  363. if (psidOwner != NULL) {
  364. LocalFree(psidOwner);
  365. }
  366. if (pacl != NULL) {
  367. LocalFree(pacl);
  368. }
  369. if (ptu != NULL) {
  370. LocalFree(ptu);
  371. }
  372. return Status;
  373. }
  374. // ***************************************************************************
  375. VOID FreeDefSD(
  376. SECURITY_DESCRIPTOR *psd)
  377. {
  378. BOOLEAN f1, f2;
  379. PSID psid = NULL;
  380. PACL pacl = NULL;
  381. UserAssert(psd != NULL);
  382. if (NT_SUCCESS(RtlGetOwnerSecurityDescriptor(psd, &psid, &f1))) {
  383. if (psid != NULL) {
  384. LocalFree(psid);
  385. }
  386. }
  387. if (NT_SUCCESS(RtlGetDaclSecurityDescriptor(psd, &f1, &pacl, &f2))) {
  388. if (pacl != NULL) {
  389. LocalFree(pacl);
  390. }
  391. }
  392. }