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.

655 lines
19 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. sspicli.cxx
  5. Abstract:
  6. sspicli
  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 "sspicli.hxx"
  16. TSspiClientParam::TSspiClientParam(
  17. VOID
  18. ) : pszTargetName(NULL),
  19. pszPrincipal(NULL),
  20. pCredLogonID(NULL),
  21. pszPackageName(NTLMSP_NAME_A),
  22. pAuthData(NULL),
  23. ClientFlags(ISC_REQ_MUTUAL_AUTH | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY),
  24. TargetDataRep(SECURITY_NATIVE_DREP),
  25. ClientActionFlags(0),
  26. ProcessIdTokenUsedByClient(-1),
  27. pszS4uClientUpn(NULL),
  28. pszS4uClientRealm(NULL),
  29. S4u2SelfFlags(0)
  30. {
  31. }
  32. HRESULT
  33. GetClientSecurityContextHandle(
  34. IN TSspiClientParam* pCliParam,
  35. IN SOCKET ServerSocket,
  36. IN SOCKET ClientSocket,
  37. IN PCredHandle phClientCred,
  38. IN ULONG cbInBuf,
  39. IN CHAR* pInBuf,
  40. IN ULONG cbOutBuf,
  41. IN CHAR* pOutBuf,
  42. OUT PCtxtHandle phClientCtxt
  43. )
  44. {
  45. THResult hRetval = S_OK;
  46. SECURITY_STATUS ProtocolStatus;
  47. THResult hProtocolStatus;
  48. ULONG ContextAttributes = 0;
  49. TimeStamp Lifetime = {0};
  50. CtxtHandle hClientCtxt;
  51. ULONG cbRead = 0;
  52. SecBufferDesc OutBuffDesc = {0};
  53. SecBuffer OutSecBuff = {0};
  54. SecBufferDesc InBuffDesc = {0};
  55. SecBuffer InSecBuff = {0};
  56. BOOL bIsContinueNeeded = FALSE;
  57. SecInvalidateHandle(phClientCtxt);
  58. SecInvalidateHandle(&hClientCtxt);
  59. //
  60. // prepare output buffer
  61. //
  62. OutBuffDesc.ulVersion = 0;
  63. OutBuffDesc.cBuffers = 1;
  64. OutBuffDesc.pBuffers = &OutSecBuff;
  65. OutSecBuff.cbBuffer = cbOutBuf;
  66. OutSecBuff.BufferType = SECBUFFER_TOKEN;
  67. OutSecBuff.pvBuffer = pOutBuf;
  68. //
  69. // prepare input buffer
  70. //
  71. InBuffDesc.ulVersion = 0;
  72. InBuffDesc.cBuffers = 1;
  73. InBuffDesc.pBuffers = &InSecBuff;
  74. InSecBuff.cbBuffer = cbRead;
  75. InSecBuff.BufferType = SECBUFFER_TOKEN;
  76. InSecBuff.pvBuffer = pInBuf;
  77. DebugPrintf(SSPI_LOG, "GetClientSecurityContextHandle calling InitializeSecurityContextA "
  78. "pszTargetName %s, ClientFlags %#x, TargetDataRep %#x, CredHandle %#x:%#x\n",
  79. pCliParam->pszTargetName, pCliParam->ClientFlags, pCliParam->TargetDataRep,
  80. phClientCred->dwUpper, phClientCred->dwLower);
  81. hRetval DBGCHK = InitializeSecurityContextA(
  82. phClientCred,
  83. NULL, // No Client context yet
  84. pCliParam->pszTargetName,
  85. pCliParam->ClientFlags,
  86. 0, // Reserved 1
  87. pCliParam->TargetDataRep,
  88. NULL, // No initial input token
  89. 0, // Reserved 2
  90. &hClientCtxt,
  91. &OutBuffDesc,
  92. &ContextAttributes,
  93. &Lifetime
  94. );
  95. bIsContinueNeeded = (S_OK == IsContinueNeeded(hRetval));
  96. DebugPrintf(SSPI_LOG, "GetClientSecurityContextHandle ISC bIsContinueNeeded %#x, hRetval %#x\n", bIsContinueNeeded, (HRESULT) hRetval);
  97. if (S_OK == IsCompleteNeeded(hRetval))
  98. {
  99. THResult hr;
  100. hr DBGCHK = CompleteAuthToken(&hClientCtxt, &OutBuffDesc);
  101. if (FAILED(hr)) // retain continue needed info
  102. {
  103. hRetval DBGNOCHK = hr;
  104. }
  105. }
  106. ProtocolStatus = (HRESULT) hRetval;
  107. hProtocolStatus DBGCHK = WriteMessage(ServerSocket,
  108. sizeof(ProtocolStatus),
  109. &ProtocolStatus);
  110. if (SUCCEEDED(hRetval))
  111. {
  112. hRetval DBGCHK = hProtocolStatus;
  113. }
  114. if (SUCCEEDED(hRetval))
  115. {
  116. hRetval DBGCHK = WriteMessage(ServerSocket,
  117. OutSecBuff.cbBuffer,
  118. OutSecBuff.pvBuffer);
  119. }
  120. while (SUCCEEDED(hRetval))
  121. {
  122. hRetval DBGCHK = ReadMessage(ClientSocket,
  123. sizeof(ProtocolStatus),
  124. &ProtocolStatus,
  125. &cbRead);
  126. if (SUCCEEDED(hRetval))
  127. {
  128. hRetval DBGCHK = ProtocolStatus;
  129. }
  130. if (SUCCEEDED(hRetval))
  131. {
  132. hRetval DBGCHK = ReadMessage(ClientSocket,
  133. cbInBuf,
  134. pInBuf,
  135. &cbRead);
  136. }
  137. else
  138. {
  139. break; // break out
  140. }
  141. if (SUCCEEDED(hRetval) && !bIsContinueNeeded)
  142. {
  143. hRetval DBGCHK = (S_OK != IsContinueNeeded(ProtocolStatus)) ? S_OK : E_ACCESSDENIED;
  144. break;
  145. }
  146. if (SUCCEEDED(hRetval))
  147. {
  148. InSecBuff.cbBuffer = cbRead;
  149. OutSecBuff.cbBuffer = cbOutBuf;
  150. DebugPrintf(SSPI_LOG, "GetClientSecurityContextHandle calling InitializeSecurityContextA "
  151. "pszTargetName %s, ClientFlags %#x, TargetDataRep %#x, hClientCtxt %#x:%#x\n",
  152. pCliParam->pszTargetName, pCliParam->ClientFlags, pCliParam->TargetDataRep,
  153. hClientCtxt.dwUpper, hClientCtxt.dwLower);
  154. hRetval DBGCHK = InitializeSecurityContextA(
  155. NULL, // no cred handle
  156. &hClientCtxt,
  157. pCliParam->pszTargetName,
  158. pCliParam->ClientFlags,
  159. 0,
  160. pCliParam->TargetDataRep,
  161. &InBuffDesc,
  162. 0,
  163. &hClientCtxt,
  164. &OutBuffDesc,
  165. &ContextAttributes,
  166. &Lifetime
  167. );
  168. }
  169. bIsContinueNeeded = (S_OK == IsContinueNeeded(hRetval));
  170. DebugPrintf(SSPI_LOG, "GetClientSecurityContextHandle ISC bIsContinueNeeded %#x, hRetval %#x\n", bIsContinueNeeded, (HRESULT) hRetval);
  171. if (S_OK == IsCompleteNeeded(hRetval))
  172. {
  173. THResult hr;
  174. hr DBGCHK = CompleteAuthToken(&hClientCtxt, &OutBuffDesc);
  175. if (FAILED(hr)) // retain continue needed info
  176. {
  177. hRetval DBGNOCHK = hr;
  178. }
  179. }
  180. //
  181. // is server listening?
  182. //
  183. if (SUCCEEDED(hRetval))
  184. {
  185. if (S_OK != IsContinueNeeded(ProtocolStatus)) // no
  186. {
  187. hRetval DBGCHK = (SEC_E_OK == (HRESULT) hRetval) ? S_OK : E_ACCESSDENIED;
  188. break;
  189. }
  190. }
  191. ProtocolStatus = (HRESULT) hRetval;
  192. hProtocolStatus DBGCHK = WriteMessage(ServerSocket,
  193. sizeof(ProtocolStatus),
  194. &ProtocolStatus);
  195. if (SUCCEEDED(hRetval))
  196. {
  197. hRetval DBGCHK = hProtocolStatus;
  198. }
  199. if (SUCCEEDED(hRetval))
  200. {
  201. hRetval DBGCHK = WriteMessage(ServerSocket,
  202. OutSecBuff.cbBuffer,
  203. OutSecBuff.pvBuffer);
  204. }
  205. }
  206. if (SUCCEEDED(hRetval))
  207. {
  208. TimeStamp CurrentTime = {0};
  209. DebugPrintf(SSPI_LOG, "***********Client authentication succeeded:**********\n");
  210. DebugPrintf(SSPI_LOG, "ClientContextHandle: %#x:%#x, ContextAttributes: %#x\n",
  211. hClientCtxt.dwUpper, hClientCtxt.dwLower, ContextAttributes);
  212. DebugPrintLocalTime(SSPI_LOG, "Lifetime", &Lifetime);
  213. GetSystemTimeAsFileTime((PFILETIME) &CurrentTime);
  214. DebugPrintSysTimeAsLocalTime(SSPI_LOG, "Current Time", &CurrentTime);
  215. *phClientCtxt = hClientCtxt;
  216. SecInvalidateHandle(&hClientCtxt)
  217. }
  218. THResult hr;
  219. if (SecIsValidHandle(&hClientCtxt))
  220. {
  221. hr DBGCHK = DeleteSecurityContext(&hClientCtxt);
  222. }
  223. return hRetval;
  224. }
  225. HRESULT
  226. GetClientImpToken(
  227. IN ULONG ProcessId,
  228. IN PCSTR pszPackageName,
  229. IN OPTIONAL PCSTR pszS4uClientUpn,
  230. IN OPTIONAL PCSTR pszS4uClientRealm,
  231. IN ULONG S4u2SelfFlags,
  232. OUT HANDLE* phToken
  233. )
  234. {
  235. THResult hRetval = S_OK;
  236. UNICODE_STRING ClientUpn = {0};
  237. UNICODE_STRING ClientRealm = {0};
  238. UNICODE_STRING Password = {0}; // ignored
  239. ULONG PackageId = 0;
  240. HANDLE hLsa = NULL;
  241. HANDLE hImpToken = NULL;
  242. TPrivilege* pPriv = NULL;
  243. *phToken = NULL;
  244. if (ProcessId != -1)
  245. {
  246. hRetval DBGCHK = GetProcessTokenByProcessId(ProcessId, &hImpToken);
  247. }
  248. else if (pszS4uClientRealm || pszS4uClientUpn)
  249. {
  250. hRetval DBGCHK = !_stricmp(pszPackageName, MICROSOFT_KERBEROS_NAME_A) ? S_OK : E_INVALIDARG;
  251. if (SUCCEEDED(hRetval))
  252. {
  253. hRetval DBGCHK = CreateUnicodeStringFromAsciiz(pszS4uClientRealm, &ClientRealm);
  254. }
  255. if (SUCCEEDED(hRetval))
  256. {
  257. hRetval DBGCHK = CreateUnicodeStringFromAsciiz(pszS4uClientUpn, &ClientUpn);
  258. }
  259. if (SUCCEEDED(hRetval))
  260. {
  261. pPriv = new TPrivilege(SE_TCB_PRIVILEGE, TRUE);
  262. hRetval DBGCHK = pPriv ? pPriv->Validate() : E_OUTOFMEMORY;
  263. }
  264. if (SUCCEEDED(hRetval))
  265. {
  266. hRetval DBGCHK = GetLsaHandleAndPackageId(
  267. pszPackageName,
  268. &hLsa,
  269. &PackageId
  270. );
  271. }
  272. if (SUCCEEDED(hRetval))
  273. {
  274. hRetval DBGCHK = KrbLsaLogonUser(
  275. hLsa,
  276. PackageId,
  277. Network, // this would cause S4u2self to be used
  278. &ClientUpn,
  279. &ClientRealm,
  280. &Password, // ignored for s4u2self
  281. S4u2SelfFlags, // Flags for s4u2self
  282. &hImpToken
  283. );
  284. }
  285. }
  286. if (SUCCEEDED(hRetval))
  287. {
  288. *phToken = hImpToken;
  289. hImpToken = NULL;
  290. }
  291. THResult hr;
  292. if (hImpToken)
  293. {
  294. hr DBGCHK = CloseHandle(hImpToken) ? S_OK : GetLastErrorAsHResult();
  295. }
  296. if (pPriv)
  297. {
  298. delete pPriv;
  299. }
  300. if (hLsa)
  301. {
  302. hr DBGCHK = LsaDeregisterLogonProcess(hLsa);
  303. }
  304. RtlFreeUnicodeString(&ClientRealm);
  305. RtlFreeUnicodeString(&ClientUpn);
  306. return hRetval;
  307. }
  308. HRESULT
  309. SspiClientStart(
  310. IN TSspiClientThreadParam* pParameter, // thread data
  311. IN SOCKET ServerSocket,
  312. IN SOCKET ClientSocket
  313. )
  314. {
  315. THResult hRetval = S_OK;
  316. TSspiClientParam* pCliParam = NULL;
  317. CredHandle hClientCred;
  318. CtxtHandle hClientCtxt;
  319. CtxtHandle hServerCtxt;
  320. ULONG cbInBuf = 0;
  321. CHAR* pInBuf = NULL;
  322. ULONG cbOutBuf = 0;
  323. CHAR* pOutBuf = NULL;
  324. TImpersonation* pImpersonation = NULL;
  325. HANDLE hImpToken = NULL;
  326. ULONG cPackages = 0;
  327. PSecPkgInfoA pPackageInfo = NULL;
  328. HANDLE hImportToken = NULL;
  329. HANDLE hExportToken = NULL;
  330. SecBuffer MarshalledContext = {0};
  331. SecPkgContext_PackageInfoA ContextPackageInfo = {0};
  332. DebugPrintf(SSPI_LOG, "SspiClientStart entering\n");
  333. SecInvalidateHandle(&hClientCred);
  334. SecInvalidateHandle(&hClientCtxt);
  335. SecInvalidateHandle(&hServerCtxt);
  336. pCliParam = dynamic_cast<TSspiClientParam*>(pParameter);
  337. hRetval DBGCHK = pCliParam ? S_OK : E_INVALIDARG;
  338. if (SUCCEEDED(hRetval))
  339. {
  340. hRetval DBGCHK = GetClientImpToken(
  341. pCliParam->ProcessIdTokenUsedByClient,
  342. pCliParam->pszPackageName,
  343. pCliParam->pszS4uClientUpn,
  344. pCliParam->pszS4uClientRealm,
  345. pCliParam->S4u2SelfFlags,
  346. &hImpToken
  347. );
  348. }
  349. if (SUCCEEDED(hRetval) && hImpToken)
  350. {
  351. pImpersonation = new TImpersonation(hImpToken);
  352. hRetval DBGCHK = pImpersonation ? pImpersonation->Validate() : E_OUTOFMEMORY;
  353. if (SUCCEEDED(hRetval))
  354. {
  355. DebugPrintf(SSPI_LOG, "************** check client token data %p ******\n", hImpToken);
  356. hRetval DBGCHK = CheckUserData();
  357. }
  358. }
  359. if (SUCCEEDED(hRetval))
  360. {
  361. hRetval DBGCHK = AcquireCredHandle(
  362. pCliParam->pszPrincipal,
  363. pCliParam->pCredLogonID,
  364. pCliParam->pszPackageName,
  365. pCliParam->pAuthData,
  366. SECPKG_CRED_OUTBOUND,
  367. &hClientCred
  368. );
  369. }
  370. if (pImpersonation)
  371. {
  372. delete pImpersonation;
  373. }
  374. if (SUCCEEDED(hRetval))
  375. {
  376. DebugPrintf(SSPI_LOG, "SspiClientStart QuerySecurityPackageInfoA \"%s\"\n", pCliParam->pszPackageName);
  377. hRetval DBGCHK = QuerySecurityPackageInfoA(pCliParam->pszPackageName, &pPackageInfo);
  378. }
  379. if (SUCCEEDED(hRetval))
  380. {
  381. pInBuf = new CHAR[pPackageInfo->cbMaxToken + sizeof(ULONG_PTR)]; // allow length prefix
  382. hRetval DBGCHK = pInBuf ? S_OK : E_OUTOFMEMORY;
  383. }
  384. if (SUCCEEDED(hRetval))
  385. {
  386. cbInBuf = pPackageInfo->cbMaxToken + sizeof(ULONG_PTR);
  387. RtlZeroMemory(pInBuf, cbInBuf);
  388. pOutBuf = new CHAR[pPackageInfo->cbMaxToken + sizeof(ULONG_PTR)]; // allow length prefix
  389. hRetval DBGCHK = pOutBuf ? S_OK : E_OUTOFMEMORY;
  390. }
  391. if (SUCCEEDED(hRetval))
  392. {
  393. cbOutBuf = pPackageInfo->cbMaxToken + sizeof(ULONG_PTR);
  394. RtlZeroMemory(pOutBuf, cbOutBuf);
  395. hRetval DBGCHK = GetClientSecurityContextHandle(
  396. pCliParam,
  397. ServerSocket,
  398. ClientSocket,
  399. &hClientCred,
  400. cbInBuf,
  401. pInBuf,
  402. cbOutBuf,
  403. pOutBuf,
  404. &hClientCtxt
  405. );
  406. }
  407. if (SUCCEEDED(hRetval))
  408. {
  409. DebugPrintf(SSPI_LOG, "SspiClientStart Writing ClientActionFlags %#x\n", pCliParam->ClientActionFlags);
  410. hRetval DBGCHK = WriteMessage(ServerSocket,
  411. sizeof(pCliParam->ClientActionFlags),
  412. &pCliParam->ClientActionFlags);
  413. }
  414. if (SUCCEEDED(hRetval) && ((pCliParam->ClientActionFlags & SSPI_ACTION_NO_QCA) == 0))
  415. {
  416. hRetval DBGCHK = CheckSecurityContextHandle(&hClientCtxt);
  417. }
  418. if (SUCCEEDED(hRetval) && ((pCliParam->ClientActionFlags & SSPI_ACTION_NO_MESSAGES) == 0))
  419. {
  420. hRetval DBGCHK = DoSspiClientWork(
  421. &hClientCtxt,
  422. ServerSocket,
  423. ClientSocket
  424. );
  425. }
  426. if (SUCCEEDED(hRetval) && ((pCliParam->ClientActionFlags & SSPI_ACTION_NO_IMPORT_EXPORT) == 0))
  427. {
  428. DebugPrintf(SSPI_LOG, "*********Client Export/Import security contexts***********");
  429. hRetval DBGCHK = QueryContextAttributesA(
  430. &hClientCtxt, // assuming client and server having the same package
  431. SECPKG_ATTR_PACKAGE_INFO,
  432. &ContextPackageInfo
  433. );
  434. MarshalledContext.cbBuffer = cbInBuf;
  435. MarshalledContext.pvBuffer = pInBuf;
  436. hRetval DBGCHK = ReadMessage(ClientSocket,
  437. MarshalledContext.cbBuffer,
  438. MarshalledContext.pvBuffer,
  439. &MarshalledContext.cbBuffer);
  440. }
  441. if (SUCCEEDED(hRetval) && ((pCliParam->ClientActionFlags & SSPI_ACTION_NO_IMPORT_EXPORT) == 0))
  442. {
  443. DebugPrintf(SSPI_LOG, "SspiClientStart calling ImportSecurityContextA pszPackageName %s\n",
  444. (ContextPackageInfo.PackageInfo ?
  445. ContextPackageInfo.PackageInfo->Name : pCliParam->pszPackageName));
  446. hRetval DBGCHK = ImportSecurityContextA(
  447. (ContextPackageInfo.PackageInfo ?
  448. ContextPackageInfo.PackageInfo->Name : pCliParam->pszPackageName),
  449. &MarshalledContext,
  450. NULL, // hImportToken
  451. &hServerCtxt
  452. );
  453. }
  454. if (SUCCEEDED(hRetval) && ((pCliParam->ClientActionFlags & SSPI_ACTION_NO_IMPORT_EXPORT) == 0))
  455. {
  456. RtlZeroMemory(&MarshalledContext, sizeof(MarshalledContext));
  457. DebugPrintf(SSPI_LOG, "SspiClientStart calling ExportSecurityContext\n");
  458. hRetval DBGCHK = ExportSecurityContext(
  459. &hClientCtxt,
  460. SECPKG_CONTEXT_EXPORT_DELETE_OLD,
  461. &MarshalledContext,
  462. &hExportToken
  463. );
  464. if (SUCCEEDED(hRetval))
  465. {
  466. SecInvalidateHandle(&hClientCtxt);
  467. hRetval DBGCHK = WriteMessage(ServerSocket,
  468. MarshalledContext.cbBuffer,
  469. MarshalledContext.pvBuffer);
  470. }
  471. if (MarshalledContext.pvBuffer)
  472. {
  473. FreeContextBuffer(MarshalledContext.pvBuffer);
  474. }
  475. }
  476. if (SUCCEEDED(hRetval) && ((pCliParam->ClientActionFlags & (SSPI_ACTION_NO_IMPORT_EXPORT | SSPI_ACTION_NO_IMPORT_EXPORT_MSG)) == 0))
  477. {
  478. hRetval DBGCHK = DoSspiServerWork(
  479. &hServerCtxt,
  480. ServerSocket,
  481. ClientSocket
  482. );
  483. }
  484. THResult hr;
  485. if (pPackageInfo)
  486. {
  487. hr DBGCHK = FreeContextBuffer(pPackageInfo);
  488. }
  489. if (SecIsValidHandle(&hClientCred))
  490. {
  491. hr DBGCHK = FreeCredentialsHandle(&hClientCred);
  492. }
  493. if (SecIsValidHandle(&hClientCtxt))
  494. {
  495. hr DBGCHK = DeleteSecurityContext(&hClientCtxt);
  496. }
  497. if (SecIsValidHandle(&hServerCtxt))
  498. {
  499. hr DBGCHK = DeleteSecurityContext(&hServerCtxt);
  500. }
  501. if (ContextPackageInfo.PackageInfo)
  502. {
  503. hr DBGCHK = FreeContextBuffer(ContextPackageInfo.PackageInfo);
  504. }
  505. if (pOutBuf)
  506. {
  507. delete [] pOutBuf;
  508. }
  509. if (pInBuf)
  510. {
  511. delete [] pInBuf;
  512. }
  513. if (hExportToken)
  514. {
  515. hr DBGCHK = CloseHandle(hExportToken) ? S_OK : GetLastErrorAsHResult();
  516. }
  517. if (hImportToken)
  518. {
  519. hr DBGCHK = CloseHandle(hImportToken) ? S_OK : GetLastErrorAsHResult();
  520. }
  521. if (hImpToken)
  522. {
  523. hr DBGCHK = CloseHandle(hImpToken) ? S_OK : GetLastErrorAsHResult();
  524. }
  525. DebugPrintf(SSPI_LOG, "SspiClientStart leaving %#x\n", (HRESULT) hRetval);
  526. return hRetval;
  527. }