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.

632 lines
18 KiB

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