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.

521 lines
16 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. namedpipes.cxx
  5. Abstract:
  6. namedpipes
  7. Author:
  8. Larry Zhu (LZhu) January 1, 2002 Created
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "precomp.hxx"
  14. #pragma hdrstop
  15. #include "namedpipes.hxx"
  16. PCTSTR g_pszPipeName = TEXT("pipetest");
  17. HRESULT
  18. GetClientImpToken(
  19. IN ULONG ProcessId,
  20. IN OPTIONAL PCWSTR pszS4uClientUpn,
  21. IN OPTIONAL PCWSTR pszS4uClientRealm,
  22. IN ULONG S4u2SelfFlags,
  23. OUT HANDLE* phToken
  24. )
  25. {
  26. THResult hRetval = S_OK;
  27. UNICODE_STRING ClientUpn = {0};
  28. UNICODE_STRING ClientRealm = {0};
  29. UNICODE_STRING Password = {0}; // ignored
  30. ULONG PackageId = 0;
  31. HANDLE hLsa = NULL;
  32. HANDLE hImpToken = NULL;
  33. TPrivilege* pPriv = NULL;
  34. *phToken = NULL;
  35. if (ProcessId)
  36. {
  37. hRetval DBGCHK = GetProcessTokenByProcessId(ProcessId, &hImpToken);
  38. }
  39. else if (pszS4uClientRealm || pszS4uClientUpn)
  40. {
  41. RtlInitUnicodeString(&ClientRealm, pszS4uClientRealm);
  42. RtlInitUnicodeString(&ClientUpn, pszS4uClientUpn);
  43. pPriv = new TPrivilege(SE_TCB_PRIVILEGE, TRUE);
  44. hRetval DBGCHK = pPriv ? pPriv->Validate() : E_OUTOFMEMORY;
  45. if (SUCCEEDED(hRetval))
  46. {
  47. hRetval DBGCHK = GetLsaHandleAndPackageId(
  48. MICROSOFT_KERBEROS_NAME_A,
  49. &hLsa,
  50. &PackageId
  51. );
  52. }
  53. if (SUCCEEDED(hRetval))
  54. {
  55. hRetval DBGCHK = KrbLsaLogonUser(
  56. hLsa,
  57. PackageId,
  58. Network, // this would cause S4u2self to be used
  59. &ClientUpn,
  60. &ClientRealm,
  61. &Password, // ignored for s4u2self
  62. S4u2SelfFlags, // Flags for s4u2self
  63. &hImpToken
  64. );
  65. }
  66. }
  67. if (SUCCEEDED(hRetval))
  68. {
  69. *phToken = hImpToken;
  70. hImpToken = NULL;
  71. }
  72. if (hImpToken)
  73. {
  74. CloseHandle(hImpToken);
  75. }
  76. if (pPriv)
  77. {
  78. delete pPriv;
  79. }
  80. if (hLsa)
  81. {
  82. LsaDeregisterLogonProcess(hLsa);
  83. }
  84. return hRetval;
  85. }
  86. DWORD WINAPI ClientThread(IN PVOID pvParam)
  87. {
  88. THResult hRetval = S_OK;
  89. CHAR Request[MAX_PATH] = {0};
  90. CHAR Reply[MAX_PATH] = {0};
  91. ULONG cbRead = 0;
  92. ULONG cbWritten = 0;
  93. HANDLE hToken = NULL;
  94. TImpersonation* pImper = NULL;
  95. HANDLE hPipe = INVALID_HANDLE_VALUE;
  96. SECURITY_ATTRIBUTES sa = {0};
  97. TClientThreadParam* pClientParam = (TClientThreadParam *) pvParam;
  98. SspiPrint(SSPI_LOG, TEXT("ClientThread entering processid %#x, pszPipeName %s, pszS4uClientRealm %s, pszS4uClientUpn %s, S4u2SelfFlags %#x, FlagsAndAttributes %#x\n"),
  99. pClientParam->ProcessId, pClientParam->pszPipeName, pClientParam->pszS4uClientRealm, pClientParam->pszS4uClientUpn, pClientParam->S4u2SelfFlags, pClientParam->FlagsAndAttributes);
  100. memset(Request, 0xef, sizeof(Request) - 1);
  101. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  102. sa.lpSecurityDescriptor = NULL; // default Dacl of caller
  103. sa.bInheritHandle = TRUE;
  104. hRetval DBGCHK = GetClientImpToken(
  105. pClientParam->ProcessId,
  106. pClientParam->pszS4uClientUpn,
  107. pClientParam->pszS4uClientRealm,
  108. pClientParam->S4u2SelfFlags,
  109. &hToken
  110. );
  111. if (SUCCEEDED(hRetval) && hToken)
  112. {
  113. pImper = new TImpersonation(hToken);
  114. hRetval DBGCHK = pImper ? pImper->Validate() : E_OUTOFMEMORY;
  115. }
  116. if (SUCCEEDED(hRetval))
  117. {
  118. SspiPrint(SSPI_LOG, TEXT("ClientPipeName %s\n"), pClientParam->pszPipeName);
  119. hRetval DBGCHK = WaitNamedPipe(
  120. pClientParam->pszPipeName,
  121. 60000
  122. ) ? S_OK : GetLastErrorAsHResult();
  123. }
  124. if (SUCCEEDED(hRetval))
  125. {
  126. hPipe = CreateFile(
  127. pClientParam->pszPipeName,
  128. GENERIC_WRITE | GENERIC_READ,
  129. FILE_SHARE_WRITE | FILE_SHARE_READ,
  130. &sa,
  131. OPEN_EXISTING,
  132. pClientParam->FlagsAndAttributes ? pClientParam->FlagsAndAttributes : (SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION),
  133. NULL
  134. );
  135. hRetval DBGCHK = (INVALID_HANDLE_VALUE != hPipe) ? S_OK : GetLastErrorAsHResult();
  136. }
  137. if (SUCCEEDED(hRetval))
  138. {
  139. hRetval DBGCHK = WriteFile(
  140. hPipe, // handle to pipe
  141. Request, // buffer to write from
  142. sizeof(Request) - 1, // number of bytes to write
  143. &cbWritten, // number of bytes written
  144. NULL // not overlapped I/O
  145. ) ? S_OK : GetLastErrorAsHResult();
  146. }
  147. if (SUCCEEDED(hRetval))
  148. {
  149. hRetval DBGCHK = ReadFile(
  150. hPipe, // handle to pipe
  151. Reply, // buffer to receive data
  152. sizeof(Reply), // size of buffer
  153. &cbRead, // number of bytes read
  154. NULL // not overlapped I/O
  155. ) ? S_OK : GetLastErrorAsHResult();
  156. }
  157. if (SUCCEEDED(hRetval))
  158. {
  159. SspiPrintHex(SSPI_LOG, TEXT("Reply"), cbRead, Reply);
  160. }
  161. if (hToken)
  162. {
  163. CloseHandle(hToken);
  164. }
  165. if (hPipe != INVALID_HANDLE_VALUE)
  166. {
  167. CloseHandle(hPipe);
  168. }
  169. if (pImper)
  170. {
  171. delete pImper;
  172. }
  173. SspiPrint(SSPI_LOG, TEXT("ClientThread leaving %#x\n"), (HRESULT) hRetval);
  174. return (HRESULT) hRetval;
  175. }
  176. DWORD WINAPI ServerWokerThread(IN PVOID pvParam)
  177. {
  178. THResult hRetval = S_OK;
  179. CHAR Request[MAX_PATH] = {0};
  180. CHAR Reply[MAX_PATH] = {0};
  181. ULONG cbBytesRead = 0;
  182. ULONG cbWritten = 0;
  183. HANDLE hToken = NULL;
  184. TServerWorkerThreadParam* pServerParam = (TServerWorkerThreadParam*) pvParam;
  185. SspiPrint(SSPI_LOG, TEXT("ServerWokerThread entering ServerPipe is %p, pszCommandLine %s\n"), pServerParam->hPipe, pServerParam->pszCommandLine);
  186. memset(Reply, 0xfe, sizeof(Reply) - 1);
  187. hRetval DBGCHK = ImpersonateNamedPipeClient(pServerParam->hPipe) ? S_OK : GetLastErrorAsHResult();
  188. if (SUCCEEDED(hRetval))
  189. {
  190. hRetval DBGCHK = ReadFile(
  191. pServerParam->hPipe, // handle to pipe
  192. Request, // buffer to receive data
  193. sizeof(Request), // size of buffer
  194. &cbBytesRead, // number of bytes read
  195. NULL // not overlapped I/O
  196. ) ? S_OK : GetLastErrorAsHResult();
  197. }
  198. if (SUCCEEDED(hRetval))
  199. {
  200. SspiPrintHex(SSPI_LOG, TEXT("Request"), cbBytesRead, Request);
  201. hRetval DBGCHK = WriteFile(
  202. pServerParam->hPipe, // handle to pipe
  203. Reply, // buffer to write from
  204. sizeof(Reply) - 1, // number of bytes to write
  205. &cbWritten, // number of bytes written
  206. NULL // not overlapped I/O
  207. ) ? S_OK : GetLastErrorAsHResult();
  208. }
  209. if (SUCCEEDED(hRetval) && pServerParam->pszCommandLine)
  210. {
  211. hRetval DBGCHK = OpenThreadToken(
  212. GetCurrentThread(),
  213. MAXIMUM_ALLOWED,
  214. TRUE,
  215. &hToken
  216. ) ? S_OK : GetLastErrorAsHResult();
  217. if (SUCCEEDED(hRetval))
  218. {
  219. hRetval DBGCHK = StartInteractiveClientProcessAsUser(
  220. hToken,
  221. pServerParam->pszCommandLine
  222. );
  223. }
  224. }
  225. RevertToSelf();
  226. if (hToken)
  227. {
  228. CloseHandle(hToken);
  229. }
  230. FlushFileBuffers(pServerParam->hPipe);
  231. DisconnectNamedPipe(pServerParam->hPipe);
  232. CloseHandle(pServerParam->hPipe);
  233. pServerParam->hPipe = INVALID_HANDLE_VALUE;
  234. SspiPrint(SSPI_LOG, TEXT("ServerWokerThread leaving %#x\n"), (HRESULT) hRetval);
  235. return (HRESULT) hRetval;
  236. }
  237. VOID
  238. Usage(
  239. IN PCTSTR pszProgram
  240. )
  241. {
  242. SspiPrint(SSPI_ERROR,
  243. TEXT("Usage: %s [-noclient] [-noserver] [-pipename <pipename>] [-application <application>]\n")
  244. TEXT("[-s4uclientupn <clientupn>] [-s4uclientrealm <clientrealm>] [-s4u2selfflags <flags>]\n")
  245. TEXT("[-clientprocessidtoimperonate <processid>] [-clientflagsandattributes <flagsandattributes>]\n"), pszProgram);
  246. exit(-1);
  247. }
  248. VOID __cdecl
  249. _tmain(
  250. IN INT argc,
  251. IN PTSTR argv[]
  252. )
  253. {
  254. THResult hRetval = S_OK;
  255. INT mark = 1;
  256. BOOLEAN bStartClient = TRUE;
  257. BOOLEAN bStartServer = TRUE;
  258. PCTSTR pszPipeName = g_pszPipeName;
  259. ULONG tid = 0;
  260. HANDLE hClientThread = NULL;
  261. HANDLE hServerWorkerThread = NULL;
  262. TClientThreadParam ClientParam = {0};
  263. TCHAR szClientPipeName[MAX_PATH] = {0};
  264. TCHAR szServerPipeName[MAX_PATH] = {0};
  265. PTSTR pszServerHost = NULL;
  266. PTSTR pszCommandLine = NULL;
  267. SECURITY_ATTRIBUTES sa = {0};
  268. SECURITY_DESCRIPTOR sd = {0};
  269. BYTE AclBuf[ 64 ] = {0};
  270. DWORD cbAcl = sizeof(AclBuf);
  271. PACL pAcl = (PACL)AclBuf;
  272. argc--;
  273. while (argc)
  274. {
  275. if (!lstrcmp(argv[mark], TEXT("-port")) && (argc > 1))
  276. {
  277. argc--; mark++;
  278. pszPipeName = argv[mark];
  279. argc--; mark++;
  280. }
  281. else if (!lstrcmp(argv[mark], TEXT("-application")) && (argc > 1))
  282. {
  283. argc--; mark++;
  284. pszCommandLine = argv[mark];
  285. argc--; mark++;
  286. }
  287. else if (!lstrcmp(argv[mark], TEXT("-su4clientupn")) && (argc > 1))
  288. {
  289. argc--; mark++;
  290. ClientParam.pszS4uClientUpn = argv[mark];
  291. argc--; mark++;
  292. }
  293. else if (!lstrcmp(argv[mark], TEXT("-clientflagsandattributes")) && (argc > 1))
  294. {
  295. argc--; mark++;
  296. ClientParam.FlagsAndAttributes = lstrtol(argv[mark], NULL, 0);
  297. argc--; mark++;
  298. }
  299. else if (!lstrcmp(argv[mark], TEXT("-su42selfflags")) && (argc > 1))
  300. {
  301. argc--; mark++;
  302. ClientParam.S4u2SelfFlags = lstrtol(argv[mark], NULL, 0);
  303. argc--; mark++;
  304. }
  305. else if (!lstrcmp(argv[mark], TEXT("-clientprocessidtoimperonate")) && (argc > 1))
  306. {
  307. argc--; mark++;
  308. ClientParam.ProcessId = lstrtol(argv[mark], NULL, 0);
  309. argc--; mark++;
  310. }
  311. else if (!lstrcmp(argv[mark], TEXT("-serverhost")) && (argc > 1))
  312. {
  313. argc--; mark++;
  314. pszServerHost = argv[mark];
  315. bStartServer = FALSE;
  316. argc--; mark++;
  317. }
  318. else if (!lstrcmp(argv[mark], TEXT("-noclient")))
  319. {
  320. argc--; mark++;
  321. bStartClient = FALSE;
  322. }
  323. else if (!lstrcmp(argv[mark],TEXT("-noserver")))
  324. {
  325. argc--; mark++;
  326. bStartServer = FALSE;
  327. }
  328. else
  329. {
  330. Usage(argv[0]);
  331. }
  332. }
  333. SspiLogOpen(TEXT("namedports.exe"), SSPI_LOG | SSPI_WARN | SSPI_ERROR);
  334. if (bStartClient)
  335. {
  336. ClientParam.pszPipeName = szClientPipeName;
  337. hRetval DBGCHK = _sntprintf(szClientPipeName, COUNTOF(szClientPipeName) - 1,
  338. TEXT("\\\\%s\\pipe\\%s"),
  339. pszServerHost ? pszServerHost : TEXT("."),
  340. pszPipeName
  341. ) > 0 ? S_OK : E_INVALIDARG;
  342. }
  343. if (SUCCEEDED(hRetval) && bStartServer)
  344. {
  345. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  346. sa.lpSecurityDescriptor = &sd;
  347. sa.bInheritHandle = TRUE;
  348. hRetval DBGCHK = BuildNamedPipeAcl(pAcl, &cbAcl) ? S_OK : GetLastErrorAsHResult();
  349. if (SUCCEEDED(hRetval))
  350. {
  351. hRetval DBGCHK = InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) ? S_OK : GetLastErrorAsHResult();
  352. }
  353. if (SUCCEEDED(hRetval))
  354. {
  355. hRetval DBGCHK = SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE) ? S_OK : GetLastErrorAsHResult();
  356. }
  357. if (SUCCEEDED(hRetval))
  358. {
  359. hRetval DBGCHK = _sntprintf(szServerPipeName, COUNTOF(szServerPipeName) - 1,
  360. TEXT("\\\\.\\pipe\\%s"),
  361. pszPipeName
  362. ) > 0 ? S_OK : E_INVALIDARG;
  363. }
  364. }
  365. if (SUCCEEDED(hRetval) && bStartClient)
  366. {
  367. hClientThread = CreateThread(NULL, 0, ClientThread, &ClientParam, 0, &tid);
  368. hRetval DBGCHK = hClientThread ? S_OK : GetLastErrorAsHResult();
  369. }
  370. while (SUCCEEDED(hRetval) && bStartServer)
  371. {
  372. TServerWorkerThreadParam ServerParam = {0};
  373. SspiPrint(SSPI_LOG, TEXT("Server waiting on pipe %s\n"), szServerPipeName);
  374. ServerParam.pszCommandLine = pszCommandLine;
  375. ServerParam.hPipe = CreateNamedPipe(
  376. szServerPipeName,
  377. PIPE_ACCESS_DUPLEX,
  378. PIPE_TYPE_BYTE | PIPE_WAIT,
  379. 1,
  380. 4096, // output buffer size
  381. 4096, // input buffer size
  382. NMPWAIT_USE_DEFAULT_WAIT, // timeout interval
  383. &sa
  384. );
  385. hRetval DBGCHK = (ServerParam.hPipe != INVALID_HANDLE_VALUE) ? S_OK : GetLastErrorAsHResult();
  386. if (SUCCEEDED(hRetval))
  387. {
  388. hRetval DBGCHK = ConnectNamedPipe(
  389. ServerParam.hPipe,
  390. NULL // no overlapped structure
  391. ) ? S_OK : GetLastErrorAsHResult();
  392. if (FAILED(hRetval) && (ERROR_PIPE_CONNECTED == HRESULT_CODE(hRetval)))
  393. {
  394. hRetval DBGCHK = S_OK;
  395. }
  396. }
  397. if (SUCCEEDED(hRetval))
  398. {
  399. hServerWorkerThread = CreateThread(NULL, 0, ServerWokerThread, &ServerParam, 0, &tid);
  400. hRetval DBGCHK = hServerWorkerThread ? S_OK : GetLastErrorAsHResult();
  401. if (FAILED(hRetval))
  402. {
  403. CloseHandle(ServerParam.hPipe);
  404. ServerParam.hPipe = INVALID_HANDLE_VALUE;
  405. }
  406. else
  407. {
  408. (VOID) WaitForSingleObject(hServerWorkerThread, INFINITE);
  409. }
  410. if (hServerWorkerThread)
  411. {
  412. CloseHandle(hServerWorkerThread);
  413. }
  414. }
  415. else if (ServerParam.hPipe != INVALID_HANDLE_VALUE)
  416. {
  417. CloseHandle(ServerParam.hPipe);
  418. }
  419. }
  420. if (SUCCEEDED(hRetval) && hClientThread)
  421. {
  422. (VOID) WaitForSingleObject(hClientThread, INFINITE);
  423. }
  424. if (hClientThread)
  425. {
  426. CloseHandle(hClientThread);
  427. }
  428. SspiLogClose();
  429. }