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.

514 lines
15 KiB

  1. /*#----------------------------------------------------------------------------
  2. **
  3. ** File: sspspm.c
  4. **
  5. ** Synopsis: Security Protocol Module for SSPI Authentication providers.
  6. **
  7. ** This module contains major funtions of the SEC_SSPI.DLL which
  8. ** allows the Internet Explorer to use SSPI providers for authentication.
  9. ** The function exported to the Internet Explorer is Ssp_Load() which
  10. ** passes the address of the Ssp__DownCall() function to the Explorer.
  11. ** Then the Explorer will call Ssp__DownCall() when it needs service from
  12. ** this SPM DLL. The two major functions called by Ssp__DownCall() to
  13. ** service Explorer's request are Ssp__PreProcessRequest() and
  14. ** Ssp__ProcessResponse(). In brief, Ssp__PreProcessRequest() is
  15. ** called before the Explorer sends out a request which does not have
  16. ** any 'Authorization' header yet. And Ssp__ProcessResponse() is called
  17. ** whenever the Explorer receives an 401 'Unauthorized' response from the
  18. ** server. This SPM DLL supports all SSPI packages which are installed
  19. ** on the machine. However, MSN will be given higher priority over the
  20. ** other SSPI packages if the user already logon to MSN; in that case,
  21. ** Ssp__PreProcessRequest() will always attach MSN authentication header
  22. ** to the out-going request.
  23. **
  24. ** This SPM DLL is called by the Internet Explorer only for its
  25. ** The Internet Explorer only calls this SPM DLL when it needs
  26. ** authentication data in its request/response. In other words, the
  27. ** Explorer never calls this SPM DLL when an authentication succeeded;
  28. ** it never calls this DLL when it decide to give up on a connection
  29. ** because of server response timeout. Because of this fact, this SPM
  30. ** DLL never has sufficient information on the state of each server
  31. ** connection; it only know its state based on the content of the last
  32. ** request and the content of the current response. For this reason, this
  33. ** SPM DLL does not keep state information for each host it has visited
  34. ** unless the information is essential.
  35. ** The security context handle returned from the first call of
  36. ** InitializeSecurityContext() for NEGOTIATE message generation is
  37. ** always the identical for a SSPI package when the same server host is
  38. ** passed. Since the server host name is always in the request/response
  39. ** header, the only information essential in generating a NEGOTIATE or
  40. ** RESPONSE is already available in the header. So unlike most SSPI
  41. ** application, this DLL will not keep the security context handle which
  42. ** it received from the SSPI function calls. Whenever it needs to call
  43. ** the SSPI function for generating a RESPONSE, it will first call the
  44. ** SSPI function without the CHALLENGE to get a security context handle.
  45. ** Then it calls the SSPI function again with the CHALLENGE to generate
  46. ** a RESPONSE.
  47. **
  48. **
  49. ** Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  50. **
  51. ** Authors: LucyC Created 25 Sept. 1995
  52. **
  53. **---------------------------------------------------------------------------*/
  54. #include "msnspmh.h"
  55. #include <ntverp.h>
  56. //
  57. // Global variable where all the SSPI Pkgs data is collected
  58. //
  59. SspData *g_pSspData;
  60. HINSTANCE g_hSecLib;
  61. BOOL g_fIsWhistler = FALSE;
  62. BOOL g_fCanUseCredMgr = FALSE;
  63. /*-----------------------------------------------------------------------------
  64. **
  65. ** Function: SpmAddSSPIPkg
  66. **
  67. ** Synopsis: This function adds a SSPI package to the SPM's package list.
  68. **
  69. ** Arguments: pData - Points to the private SPM data structure containing
  70. ** the package list and the package info.
  71. ** pPkgName - package name
  72. ** cbMaxToken - max size of security token
  73. **
  74. ** Returns: The index in the package list where this new package is added.
  75. ** If failed to add the new package, SSPPKG_ERROR is returned.
  76. **
  77. ** History: LucyC Created 21 Oct. 1995
  78. **
  79. **---------------------------------------------------------------------------*/
  80. UCHAR
  81. SpmAddSSPIPkg (
  82. SspData *pData,
  83. LPTSTR pPkgName,
  84. ULONG cbMaxToken
  85. )
  86. {
  87. if ( !(pData->PkgList[pData->PkgCnt] =
  88. LocalAlloc(0, sizeof(SSPAuthPkg))))
  89. {
  90. return SSPPKG_ERROR;
  91. }
  92. if ( !(pData->PkgList[pData->PkgCnt]->pName =
  93. LocalAlloc(0, lstrlen(pPkgName)+1)))
  94. {
  95. LocalFree(pData->PkgList[pData->PkgCnt]);
  96. pData->PkgList[pData->PkgCnt] = NULL;
  97. return SSPPKG_ERROR;
  98. }
  99. lstrcpy (pData->PkgList[pData->PkgCnt]->pName, pPkgName);
  100. pData->PkgList[ pData->PkgCnt ]->Capabilities = 0 ;
  101. pData->PkgList[ pData->PkgCnt ]->cbMaxToken = cbMaxToken;
  102. //
  103. // Determine if this package supports anything of interest to
  104. // us.
  105. //
  106. if ( lstrcmpi( pPkgName, NTLMSP_NAME_A ) == 0 )
  107. {
  108. //
  109. // NTLM supports the standard credential structure
  110. //
  111. pData->PkgList[ pData->PkgCnt ]->Capabilities |= SSPAUTHPKG_SUPPORT_NTLM_CREDS ;
  112. }
  113. else if ( lstrcmpi( pPkgName, "Negotiate" ) == 0 )
  114. {
  115. //
  116. // Negotiate supports that cred structure too
  117. //
  118. pData->PkgList[ pData->PkgCnt ]->Capabilities |= SSPAUTHPKG_SUPPORT_NTLM_CREDS ;
  119. }
  120. else
  121. {
  122. //
  123. // Add more comparisons here, eventually.
  124. //
  125. ;
  126. }
  127. pData->PkgCnt++;
  128. return (pData->PkgCnt - 1);
  129. }
  130. /*-----------------------------------------------------------------------------
  131. **
  132. ** Function: SpmFreePkgList
  133. **
  134. ** Synopsis: This function frees memory allocated for the package list.
  135. **
  136. ** Arguments: pData - Points to the private SPM data structure containing
  137. ** the package list and the package info.
  138. **
  139. ** Returns: void.
  140. **
  141. ** History: LucyC Created 21 Oct. 1995
  142. **
  143. **---------------------------------------------------------------------------*/
  144. VOID
  145. SpmFreePkgList (
  146. SspData *pData
  147. )
  148. {
  149. int ii;
  150. for (ii = 0; ii < pData->PkgCnt; ii++)
  151. {
  152. LocalFree(pData->PkgList[ii]->pName);
  153. LocalFree(pData->PkgList[ii]);
  154. }
  155. LocalFree(pData->PkgList);
  156. }
  157. /*-----------------------------------------------------------------------------
  158. **
  159. ** Function: Ssp__Unload
  160. **
  161. ** Synopsis: This function is called by the Internet Explorer before
  162. ** the SPM DLL is unloaded from the memory.
  163. **
  164. ** Arguments: fpUI - From Explorer for making all UI_SERVICE call
  165. ** pvOpaqueOS - From Explorer for making all UI_SERVICE call
  166. ** htspm - the SPM structure which contains the global data
  167. ** storage for this SPM DLL.
  168. **
  169. ** Returns: always returns SPM_STATUS_OK, which means successful.
  170. **
  171. ** History: LucyC Created 25 Sept. 1995
  172. **
  173. **---------------------------------------------------------------------------*/
  174. DWORD SSPI_Unload()
  175. {
  176. if (g_pSspData != NULL)
  177. {
  178. SpmFreePkgList(g_pSspData);
  179. LocalFree(g_pSspData);
  180. g_pSspData = NULL;
  181. }
  182. if (g_hSecLib)
  183. {
  184. FreeLibrary (g_hSecLib);
  185. g_hSecLib = NULL;
  186. }
  187. return SPM_STATUS_OK;
  188. }
  189. /*-----------------------------------------------------------------------------
  190. **
  191. ** Function: SspSPM_InitData
  192. **
  193. ** Synopsis: This function allocates and initializes global data structure
  194. ** of the SPM DLL.
  195. **
  196. ** Arguments:
  197. **
  198. ** Returns: Pointer to the allocated global data structure.
  199. **
  200. ** History: LucyC Created 25 Sept. 1995
  201. **
  202. **---------------------------------------------------------------------------*/
  203. LPVOID SSPI_InitGlobals(void)
  204. {
  205. SspData *pData = NULL;
  206. OSVERSIONINFO VerInfo;
  207. UCHAR lpszDLL[SSP_SPM_DLL_NAME_SIZE];
  208. INIT_SECURITY_INTERFACE addrProcISI = NULL;
  209. SECURITY_STATUS sstat;
  210. ULONG ii, cntPkg;
  211. PSecPkgInfo pPkgInfo = NULL;
  212. PSecurityFunctionTable pFuncTbl = NULL;
  213. if (g_pSspData)
  214. return g_pSspData;
  215. //
  216. // Setup registry to enable MSN authentication package
  217. // MSNSetupSspiReg();
  218. //
  219. //
  220. // Initialize SSP SPM Global Data
  221. //
  222. //
  223. // Find out which security DLL to use, depending on
  224. // whether we are on NT or Win95
  225. //
  226. VerInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  227. if (!GetVersionEx (&VerInfo)) // If this fails, something has gone wrong
  228. {
  229. return (NULL);
  230. }
  231. if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  232. {
  233. lstrcpy (lpszDLL, SSP_SPM_NT_DLL);
  234. if ((VerInfo.dwMajorVersion >= 5) &&
  235. (VerInfo.dwMinorVersion >= 1))
  236. {
  237. DWORD dwMaximumPersist = 0;
  238. g_fIsWhistler = TRUE;
  239. }
  240. else
  241. {
  242. g_fIsWhistler = FALSE;
  243. }
  244. }
  245. else if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  246. {
  247. lstrcpy (lpszDLL, SSP_SPM_WIN95_DLL);
  248. }
  249. else if (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_UNIX)
  250. {
  251. lstrcpy (lpszDLL, SSP_SPM_UNIX_DLL);
  252. }
  253. else
  254. {
  255. return (NULL);
  256. }
  257. if (!(pData = (SspData *) LocalAlloc(0, sizeof(SspData)))) {
  258. return(NULL);
  259. }
  260. //
  261. // Keep these information in global SPM
  262. //
  263. ZeroMemory (pData, sizeof(SspData));
  264. pData->MsnPkg = SSPPKG_NO_PKG;
  265. //
  266. // Load Security DLL
  267. //
  268. g_hSecLib = LoadLibrary (lpszDLL);
  269. if (g_hSecLib == NULL)
  270. {
  271. // This should never happen.
  272. goto Cleanup;
  273. }
  274. #ifdef UNIX
  275. // A hack to undo the mistake in the sspi.h file. The change should be made
  276. // to sspi.h
  277. #if !defined(_UNICODE)
  278. #undef SECURITY_ENTRYPOINT_ANSI
  279. #define SECURITY_ENTRYPOINT_ANSI "InitSecurityInterfaceA"
  280. #endif
  281. addrProcISI = (INIT_SECURITY_INTERFACE) GetProcAddress( g_hSecLib,
  282. SECURITY_ENTRYPOINT_ANSI);
  283. #else
  284. addrProcISI = (INIT_SECURITY_INTERFACE) GetProcAddress( g_hSecLib,
  285. SECURITY_ENTRYPOINT);
  286. #endif /* UNIX */
  287. if (addrProcISI == NULL)
  288. {
  289. goto Cleanup;
  290. }
  291. //
  292. // Get the SSPI function table
  293. //
  294. pFuncTbl = (*addrProcISI)();
  295. //
  296. // If we already loaded MSNSSPC.DLL explicitly, PkgCnt will not be zero;
  297. // in that case, we only support MSN SSPI and do not need to call
  298. // EnumerateSecurityPackages.
  299. //
  300. // So if we did not load MSNSSPC.DLL (i.e. PkgCnt is zero), we need to
  301. // get the list of SSPI packages which we support from
  302. // EnumerateSecurityPackages.
  303. //
  304. if (pData->PkgCnt == 0)
  305. {
  306. //
  307. // Get list of packages supported
  308. //
  309. sstat = (*(pFuncTbl->EnumerateSecurityPackages))(&cntPkg, &pPkgInfo);
  310. if (sstat != SEC_E_OK || pPkgInfo == NULL)
  311. {
  312. //
  313. // ??? Should we give up here ???
  314. // EnumerateSecurityPackage() failed
  315. //
  316. goto Cleanup;
  317. }
  318. if (cntPkg)
  319. {
  320. //
  321. // Create the package list
  322. //
  323. if (!(pData->PkgList = (PSSPAuthPkg *)LocalAlloc(0,
  324. cntPkg*sizeof(PSSPAuthPkg))))
  325. {
  326. goto Cleanup;
  327. }
  328. }
  329. for (ii = 0; ii < cntPkg; ii++)
  330. {
  331. if (lstrcmp (pPkgInfo[ii].Name, MSNSP_NAME) == 0)
  332. {
  333. //DebugTrace(SSPSPMID, "Found MSN SSPI package\n");
  334. pData->MsnPkg = SpmAddSSPIPkg (
  335. pData,
  336. MSNSP_NAME,
  337. MAX_AUTH_MSG_SIZE // 11000 hard-coded
  338. );
  339. if (pData->MsnPkg == SSPPKG_ERROR)
  340. {
  341. goto Cleanup;
  342. }
  343. }
  344. else
  345. {
  346. //DebugTrace(SSPSPMID, "Found %s SSPI package\n",
  347. // pPkgInfo[ii].Name);
  348. if (SpmAddSSPIPkg (pData,
  349. pPkgInfo[ii].Name,
  350. pPkgInfo[ii].cbMaxToken
  351. ) == SSPPKG_ERROR)
  352. {
  353. goto Cleanup;
  354. }
  355. }
  356. }
  357. }
  358. pData->pFuncTbl = pFuncTbl;
  359. pData->bKeepList = TRUE; // By default, keep a list of non-MSN servers
  360. if (pData->PkgCnt == 0)
  361. {
  362. goto Cleanup;
  363. }
  364. g_pSspData = pData;
  365. pData = NULL;
  366. Cleanup:
  367. if( pPkgInfo != NULL )
  368. {
  369. //
  370. // Free buffer returned by the enumerate security package function
  371. //
  372. (*(pFuncTbl->FreeContextBuffer))(pPkgInfo);
  373. }
  374. if( pData != NULL )
  375. {
  376. SpmFreePkgList (pData);
  377. }
  378. return (g_pSspData);
  379. }
  380. INT
  381. GetPkgId(LPTSTR lpszPkgName)
  382. {
  383. int ii;
  384. if ( g_pSspData == NULL )
  385. {
  386. return -1;
  387. }
  388. for (ii = 0; ii < g_pSspData->PkgCnt; ii++)
  389. {
  390. #ifdef UNIX
  391. if (!lstrcmpi(g_pSspData->PkgList[ii]->pName, lpszPkgName))
  392. #else
  393. if (!lstrcmp(g_pSspData->PkgList[ii]->pName, lpszPkgName))
  394. #endif /* UNIX */
  395. {
  396. return(ii);
  397. }
  398. }
  399. return(-1);
  400. }
  401. DWORD
  402. GetPkgCapabilities(
  403. INT Package
  404. )
  405. {
  406. if ( Package < g_pSspData->PkgCnt )
  407. {
  408. return g_pSspData->PkgList[ Package ]->Capabilities ;
  409. }
  410. else
  411. return 0 ;
  412. }
  413. ULONG
  414. GetPkgMaxToken(
  415. INT Package
  416. )
  417. {
  418. if ( Package < g_pSspData->PkgCnt )
  419. {
  420. return g_pSspData->PkgList[ Package ]->cbMaxToken;
  421. }
  422. else {
  423. // be compatible with old static buffer size
  424. return MAX_AUTH_MSG_SIZE;
  425. }
  426. }
  427. //
  428. // Calls to this function are serialized
  429. //
  430. DWORD_PTR SSPI_InitScheme (LPCSTR lpszScheme)
  431. {
  432. int ii;
  433. if (!SSPI_InitGlobals())
  434. return 0;
  435. // Once initialized, check to see if this scheme is installed
  436. for (ii = 0; ii < g_pSspData->PkgCnt &&
  437. #ifdef UNIX
  438. lstrcmpi (g_pSspData->PkgList[ii]->pName, lpszScheme); ii++);
  439. #else
  440. lstrcmp (g_pSspData->PkgList[ii]->pName, lpszScheme); ii++);
  441. #endif /* UNIX */
  442. if (ii >= g_pSspData->PkgCnt)
  443. {
  444. // This scheme is not installed on this machine
  445. return (0);
  446. }
  447. return ((DWORD_PTR)g_pSspData);
  448. }