Source code of Windows XP (NT5)
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.

714 lines
23 KiB

  1. /*--
  2. Copyright (c) 1995-1998 Microsoft Corporation
  3. Module Name: AUTH.CPP
  4. Author: Arul Menezes
  5. Abstract: Authentication
  6. --*/
  7. #include "pch.h"
  8. #pragma hdrstop
  9. #include "httpd.h"
  10. #define IsAccessAllowed(a,b,c,d) TRUE
  11. #define NTLM_DOMAIN TEXT("Domain") // dummy data.
  12. #define SEC_SUCCESS(Status) ((Status) >= 0)
  13. #ifndef OLD_CE_BUILD
  14. BOOL NTLMServerContext(
  15. PSEC_WINNT_AUTH_IDENTITY pAuthIdentity,
  16. PAUTH_NTLM pAS,BYTE *pIn, DWORD cbIn, BYTE *pOut,
  17. DWORD *pcbOut, BOOL *pfDone
  18. );
  19. BOOL NTLMClientContext(
  20. PSEC_WINNT_AUTH_IDENTITY pAuthIdentity,
  21. PAUTH_NTLM pAS, BYTE *pIn, DWORD cbIn,
  22. BYTE *pOut, DWORD *pcbOut
  23. );
  24. #endif
  25. AUTHLEVEL GetAuthFromACL(PAUTH_NTLM pAuth, PWSTR wszUser, PWSTR wszVRootUserList);
  26. void AuthInitialize(CReg *pReg, BOOL * pfBasicAuth, BOOL * pfNTLMAuth)
  27. {
  28. *pfBasicAuth = pReg->ValueDW(RV_BASIC);
  29. #ifdef OLD_CE_BUILD
  30. // No passthrough Auth on CE 2.11 devices, set it to 0 to avoid misconfigurations
  31. *pfNTLMAuth = 0;
  32. #else
  33. *pfNTLMAuth = pReg->ValueDW(RV_NTLM);
  34. #endif
  35. }
  36. // For calls to Basic Authentication, only called during the parsing stage.
  37. BOOL HandleBasicAuth(PSTR pszData, PSTR* ppszUser, PSTR *ppszPassword,
  38. AUTHLEVEL* pAuth, PAUTH_NTLM pNTLMState, WCHAR *wszVRootUserList)
  39. {
  40. char szUserName[MAXUSERPASS];
  41. DWORD dwLen = sizeof(szUserName);
  42. *pAuth = AUTH_PUBLIC;
  43. *ppszUser = NULL;
  44. // decode the base64
  45. Base64Decode(pszData, szUserName, &dwLen);
  46. // find the password
  47. PSTR pszPassword = strchr(szUserName, ':');
  48. if (!pszPassword)
  49. {
  50. TraceTag(ttidWebServer, "Bad Format for Basic userpass(%s)-->(%s)", pszData, szUserName);
  51. return FALSE;
  52. }
  53. *pszPassword++ = 0; // seperate user & pass
  54. WCHAR wszPassword[MAXUSERPASS];
  55. MyA2W(pszPassword, wszPassword, CCHSIZEOF(wszPassword));
  56. WCHAR wszUserName[MAXUSERPASS];
  57. MyA2W(szUserName,wszUserName, CCHSIZEOF(wszUserName));
  58. // We save the data no matter what, for logging purposes and for possible
  59. // GetServerVariable call.
  60. *ppszUser = MySzDupA(szUserName);
  61. *ppszPassword = MySzDupA(pszPassword);
  62. // If AUTH_USER has been granted, check to see if they're an administrator.
  63. // In BASIC we can only check against the name (no NTLM group info)
  64. #ifdef UNDER_CE
  65. if (CheckPassword(wszPassword))
  66. {
  67. *pAuth = GetAuthFromACL(NULL,wszUserName,wszVRootUserList);
  68. return TRUE;
  69. }
  70. #endif
  71. #ifndef OLD_CE_BUILD
  72. if (g_pVars->m_fNTLMAuth && BasicToNTLM(pNTLMState, wszPassword,wszUserName,pAuth,wszVRootUserList))
  73. {
  74. return TRUE;
  75. }
  76. #endif
  77. TraceTag(ttidWebServer, "Failed logon with Basic userpass(%s)-->(%s)(%s)", pszData, szUserName, pszPassword);
  78. return FALSE;
  79. }
  80. #ifdef OLD_CE_BUILD
  81. // The web server beta doesn't have NTLM, but it uses this file so we
  82. // don't use AuthStub.cpp here
  83. BOOL CHttpRequest::HandleNTLMAuth(PSTR pszNTLMData)
  84. {
  85. return FALSE;
  86. }
  87. BOOL NTLMInitLib(PAUTH_NTLM pNTLMState)
  88. {
  89. return FALSE;
  90. }
  91. void FreeNTLMHandles(PAUTH_NTLM pNTLMState)
  92. {
  93. ;
  94. }
  95. #else
  96. // This function is called 2 times during an NTLM auth session. The first
  97. // time it has the Client user name, domain,... which it forwards to DC or
  98. // looks in registry for (this NTLM detail is transparent to httpd)
  99. // On 2nd time it has the client's response, which either is or is not
  100. // enough to grant access to page. On 2nd pass, free up all NTLM context data.
  101. // FILTER NOTES: On IIS no user name or password info is given to the filter
  102. // on NTLM calls, so neither do we. (WinCE does give BASIC data, though).
  103. // The main reason this is is that
  104. BOOL CHttpRequest::HandleNTLMAuth(PSTR pszNTLMData)
  105. {
  106. DEBUG_CODE_INIT;
  107. BOOL ret = FALSE;
  108. DWORD dwIn;
  109. DWORD dwOut;
  110. BOOL fDone = FALSE;
  111. PBYTE pOutBuf = NULL;
  112. PBYTE pInBuf = NULL; // Base64 decoded data from pszNTLMData
  113. // Are the NTLM libs loaded already?
  114. if (NTLM_NO_INIT_LIB == m_NTLMState.m_Conversation)
  115. {
  116. if ( ! NTLMInitLib(&m_NTLMState))
  117. myretleave(FALSE,94);
  118. }
  119. dwOut = g_pVars->m_cbNTLMMax;
  120. if (NULL == (pOutBuf = MyRgAllocNZ(BYTE,dwOut)))
  121. myleave(360);
  122. if (NULL == m_pszNTLMOutBuf)
  123. {
  124. // We will later Base64Encode pOutBuf later, encoding writes 4 outbut bytes
  125. // for every 3 input bytes
  126. if (NULL == (m_pszNTLMOutBuf = MyRgAllocNZ(CHAR,dwOut*(4/3) + 1)))
  127. myleave(361);
  128. }
  129. dwIn = strlen(pszNTLMData) + 1;
  130. if (NULL == (pInBuf = MyRgAllocNZ(BYTE,dwIn)))
  131. myleave(363);
  132. Base64Decode(pszNTLMData,(PSTR) pInBuf,&dwIn);
  133. // On the 1st pass this gets a data blob to be sent back to the client
  134. // broweser in pOutBuf, which is encoded to m_pszNTLMOutBuf. On the 2nd
  135. // pass it either authenticates or fails.
  136. if (! NTLMServerContext(NULL, &m_NTLMState, pInBuf,
  137. dwIn,pOutBuf,&dwOut,&fDone))
  138. {
  139. // Note: We MUST free the m_pszNTMLOutBuf on 2nd pass failure. If the
  140. // client recieves the blob on a failure
  141. // it will consider the web server to be malfunctioning and will not send
  142. // another set of data, and will not prompt the user for a password.
  143. MyFree(m_pszNTLMOutBuf);
  144. // Setting to DONE will cause the local structs to be freed; they must
  145. // be fresh in case browser attempts to do NTLM again with new user name/
  146. // password on same session. Don't bother unloading the lib.
  147. m_NTLMState.m_Conversation = NTLM_DONE;
  148. myleave(362);
  149. }
  150. if (fDone)
  151. {
  152. TraceTag(ttidWebServer, "NTLM Successfully authenticated user");
  153. m_AuthLevelGranted = GetAuthFromACL(&m_NTLMState,NULL,m_wszVRootUserList);
  154. m_dwAuthFlags |= m_AuthLevelGranted;
  155. m_NTLMState.m_Conversation = NTLM_DONE;
  156. MyFree(m_pszNTLMOutBuf);
  157. myretleave(TRUE,0);
  158. }
  159. Base64Encode(pOutBuf,dwOut,m_pszNTLMOutBuf);
  160. ret = TRUE;
  161. done:
  162. TraceTag(ttidWebServer, "HandleNTLMAuthent died, err = %d, gle = %d",err,GetLastError());
  163. MyFree(pOutBuf);
  164. MyFree(pInBuf);
  165. return ret;
  166. }
  167. // Sets up NTLM info in the passed data structure. This fcn loads the library,
  168. // gets the function table, and determines the maximum buffer size.
  169. // stolen from osinternal\comm\test\security\sockauth\security.c
  170. BOOL NTLMInitLib(PAUTH_NTLM pNTLMState)
  171. {
  172. DEBUG_CODE_INIT;
  173. FARPROC pInit;
  174. SECURITY_STATUS ss;
  175. PSecPkgInfo pkgInfo;
  176. BOOL ret = FALSE;
  177. PSecurityFunctionTable pLocal = NULL;
  178. // load and initialize the ntlm ssp
  179. //
  180. if (g_pVars->m_pNTLMFuncs)
  181. {
  182. pNTLMState->m_Conversation = NTLM_NO_INIT_CONTEXT;
  183. return TRUE;
  184. }
  185. g_pVars->m_hNTLMLib = LoadLibrary (NTLM_DLL_NAME);
  186. if (NULL == g_pVars->m_hNTLMLib)
  187. myleave(700);
  188. pInit = (FARPROC) GetProcAddress (g_pVars->m_hNTLMLib, SECURITY_ENTRYPOINT_CE);
  189. if (NULL == pInit)
  190. myleave(701);
  191. pLocal = (PSecurityFunctionTable) pInit ();
  192. if (NULL == pLocal)
  193. myleave(702);
  194. // Query for the package we're interested in
  195. //
  196. ss = pLocal->QuerySecurityPackageInfo (NTLM_PACKAGE_NAME, &pkgInfo);
  197. if (!SEC_SUCCESS(ss))
  198. myleave(703);
  199. g_pVars->m_cbNTLMMax = pkgInfo->cbMaxToken;
  200. pLocal->FreeContextBuffer (pkgInfo);
  201. // The libraries have been set, but pNTLMState's structures are still empty
  202. pNTLMState->m_Conversation = NTLM_NO_INIT_CONTEXT;
  203. TraceTag(ttidWebServer, "NTLM Libs successfully initialized");
  204. ret = TRUE;
  205. done:
  206. if (FALSE == ret)
  207. {
  208. // Don't worry about freeing pkgInfo, it was freed right after creation
  209. // anyway - no chance to go wrong
  210. MyFreeLib (g_pVars->m_hNTLMLib);
  211. // Set everything to false so httpd doesn't think we have legit data later.
  212. memset(pNTLMState, 0 , sizeof(AUTH_NTLM));
  213. }
  214. else
  215. {
  216. g_pVars->m_pNTLMFuncs = pLocal; // Flag that shows we've initialized
  217. }
  218. TraceTag(ttidWebServer, "NTLMInitLib failed, err = %d, GLE = 0x%08x",err,
  219. GetLastError());
  220. return ret;
  221. }
  222. // Unload the contexts. The library is NOT freed in this call, only freed
  223. // in CHttpRequest destructor.
  224. void FreeNTLMHandles(PAUTH_NTLM pNTLMState)
  225. {
  226. if (NULL == pNTLMState || NULL == g_pVars->m_pNTLMFuncs)
  227. return;
  228. if (pNTLMState->m_fHaveCtxtHandle)
  229. g_pVars->m_pNTLMFuncs->DeleteSecurityContext (&pNTLMState->m_hctxt);
  230. if (pNTLMState->m_fHaveCredHandle)
  231. g_pVars->m_pNTLMFuncs->FreeCredentialHandle (&pNTLMState->m_hcred);
  232. pNTLMState->m_fHaveCredHandle = FALSE;
  233. pNTLMState->m_fHaveCtxtHandle = FALSE;
  234. }
  235. // Given Basic authentication data, we try to "forge" and NTLM request
  236. // This fcn simulates a client+server talking to each other, though it's in the
  237. // same proc. The client is "virtual," doesn't refer to the http client
  238. // pNTLMState is CHttpRequest::m_NTLMState
  239. BOOL BasicToNTLM(PAUTH_NTLM pNTLMState, WCHAR * wszPassword, WCHAR * wszRemoteUser,
  240. AUTHLEVEL *pAuth, WCHAR *wszVRootUserList)
  241. {
  242. DEBUG_CODE_INIT;
  243. AUTH_NTLM ClientState; // forges the client role
  244. AUTH_NTLM ServerState; // forges the server role
  245. BOOL fDone = FALSE;
  246. PBYTE pClientOutBuf = NULL;
  247. PBYTE pServerOutBuf = NULL;
  248. DWORD cbServerBuf;
  249. DWORD cbClientBuf;
  250. DEBUGCHK(wszPassword != NULL && wszRemoteUser != NULL && pNTLMState != NULL);
  251. SEC_WINNT_AUTH_IDENTITY AuthIdentityClient = {
  252. (unsigned short *)wszRemoteUser, wcslen(wszRemoteUser),
  253. (unsigned short *)NTLM_DOMAIN,sizeof(NTLM_DOMAIN)/sizeof(TCHAR) - 1,
  254. (unsigned short *)wszPassword, wcslen(wszPassword),
  255. 0}; // dummy domain needed
  256. memset(&ServerState,0,sizeof(AUTH_NTLM));
  257. memset(&ClientState,0,sizeof(AUTH_NTLM));
  258. // 1st pass through, load up library.
  259. if (NTLM_NO_INIT_LIB == pNTLMState->m_Conversation)
  260. {
  261. if ( ! NTLMInitLib(pNTLMState))
  262. myleave(369);
  263. pNTLMState->m_Conversation = NTLM_NO_INIT_CONTEXT;
  264. }
  265. // NTLM auth functions seem to expect that these buffer will be zeroed.
  266. pClientOutBuf = MyRgAllocZ(BYTE,g_pVars->m_cbNTLMMax);
  267. if (NULL == pClientOutBuf)
  268. myleave(370);
  269. pServerOutBuf = MyRgAllocZ(BYTE,g_pVars->m_cbNTLMMax);
  270. if (NULL == pServerOutBuf)
  271. myleave(371);
  272. ServerState.m_Conversation = NTLM_NO_INIT_CONTEXT;
  273. ClientState.m_Conversation = NTLM_NO_INIT_CONTEXT;
  274. cbClientBuf = cbServerBuf = g_pVars->m_cbNTLMMax;
  275. // Main loop that forges client and server talking.
  276. while (!fDone)
  277. {
  278. cbClientBuf = g_pVars->m_cbNTLMMax;
  279. if (! NTLMClientContext(&AuthIdentityClient,&ClientState,pServerOutBuf,
  280. cbServerBuf, pClientOutBuf, &cbClientBuf))
  281. {
  282. myleave(372);
  283. }
  284. cbServerBuf = g_pVars->m_cbNTLMMax;
  285. if (! NTLMServerContext(&AuthIdentityClient,&ServerState, pClientOutBuf,
  286. cbClientBuf, pServerOutBuf, &cbServerBuf, &fDone))
  287. {
  288. myleave(373);
  289. }
  290. }
  291. done:
  292. TraceTag(ttidWebServer, "Unable to convert Basic Auth to NTLM Auth, err = %d",err);
  293. if (fDone)
  294. {
  295. *pAuth = GetAuthFromACL(&ServerState,wszRemoteUser,wszVRootUserList);
  296. }
  297. MyFree(pClientOutBuf);
  298. MyFree(pServerOutBuf);
  299. FreeNTLMHandles(&ServerState);
  300. FreeNTLMHandles(&ClientState);
  301. return fDone;
  302. }
  303. // This calls the DC (or goes to registry in local case), either getting a
  304. // data blob to return to client or granting auth or denying.
  305. // stolen from osinternal\comm\test\security\sockauth\security.c
  306. BOOL NTLMServerContext(
  307. PSEC_WINNT_AUTH_IDENTITY pAuthIdentity,
  308. PAUTH_NTLM pAS, // NTLM state info
  309. BYTE *pIn,
  310. DWORD cbIn,
  311. BYTE *pOut,
  312. DWORD *pcbOut,
  313. BOOL *pfDone)
  314. {
  315. SECURITY_STATUS ss;
  316. TimeStamp Lifetime;
  317. SecBufferDesc OutBuffDesc;
  318. SecBuffer OutSecBuff;
  319. SecBufferDesc InBuffDesc;
  320. SecBuffer InSecBuff;
  321. ULONG ContextAttributes;
  322. if (NTLM_NO_INIT_CONTEXT == pAS->m_Conversation)
  323. {
  324. ss = g_pVars->m_pNTLMFuncs->AcquireCredentialsHandle (
  325. NULL, // principal
  326. NTLM_PACKAGE_NAME,
  327. SECPKG_CRED_INBOUND,
  328. NULL, // LOGON id
  329. pAuthIdentity,
  330. NULL, // get key fn
  331. NULL, // get key arg
  332. &pAS->m_hcred,
  333. &Lifetime
  334. );
  335. if (SEC_SUCCESS (ss))
  336. pAS->m_fHaveCredHandle = TRUE;
  337. else
  338. {
  339. TraceTag(ttidWebServer, "NTLM AcquireCreds failed: %X", ss);
  340. return(FALSE);
  341. }
  342. }
  343. // prepare output buffer
  344. //
  345. OutBuffDesc.ulVersion = 0;
  346. OutBuffDesc.cBuffers = 1;
  347. OutBuffDesc.pBuffers = &OutSecBuff;
  348. OutSecBuff.cbBuffer = *pcbOut;
  349. OutSecBuff.BufferType = SECBUFFER_TOKEN;
  350. OutSecBuff.pvBuffer = pOut;
  351. // prepare input buffer
  352. //
  353. InBuffDesc.ulVersion = 0;
  354. InBuffDesc.cBuffers = 1;
  355. InBuffDesc.pBuffers = &InSecBuff;
  356. InSecBuff.cbBuffer = cbIn;
  357. InSecBuff.BufferType = SECBUFFER_TOKEN;
  358. InSecBuff.pvBuffer = pIn;
  359. ss = g_pVars->m_pNTLMFuncs->AcceptSecurityContext (
  360. &pAS->m_hcred,
  361. (pAS->m_Conversation == NTLM_PROCESSING) ? &pAS->m_hctxt : NULL,
  362. &InBuffDesc,
  363. 0, // context requirements
  364. SECURITY_NATIVE_DREP,
  365. &pAS->m_hctxt,
  366. &OutBuffDesc,
  367. &ContextAttributes,
  368. &Lifetime
  369. );
  370. if (!SEC_SUCCESS (ss))
  371. {
  372. TraceTag(ttidWebServer, "NTLM init context failed: %X", ss);
  373. return FALSE;
  374. }
  375. pAS->m_fHaveCtxtHandle = TRUE;
  376. // Complete token -- if applicable
  377. //
  378. if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss))
  379. {
  380. if (g_pVars->m_pNTLMFuncs->CompleteAuthToken)
  381. {
  382. ss = g_pVars->m_pNTLMFuncs->CompleteAuthToken (&pAS->m_hctxt, &OutBuffDesc);
  383. if (!SEC_SUCCESS(ss))
  384. {
  385. TraceTag(ttidWebServer, " NTLM complete failed: %X", ss);
  386. return FALSE;
  387. }
  388. }
  389. else
  390. {
  391. TraceTag(ttidWebServer, "Complete not supported.");
  392. return FALSE;
  393. }
  394. }
  395. *pcbOut = OutSecBuff.cbBuffer;
  396. pAS->m_Conversation = NTLM_PROCESSING;
  397. *pfDone = !((SEC_I_CONTINUE_NEEDED == ss) ||
  398. (SEC_I_COMPLETE_AND_CONTINUE == ss));
  399. return TRUE;
  400. }
  401. // Forges the client browser's part in NTLM communication if the browser
  402. // sent a Basic request. This is used primarily for Netscape clients, which only
  403. // supports Basic.
  404. // stolen from osinternal\comm\test\security\sockauth\security.c
  405. BOOL NTLMClientContext(
  406. PSEC_WINNT_AUTH_IDENTITY pAuthIdentity,
  407. PAUTH_NTLM pAS, // NTLM state info
  408. BYTE *pIn,
  409. DWORD cbIn,
  410. BYTE *pOut,
  411. DWORD *pcbOut)
  412. {
  413. SECURITY_STATUS ss;
  414. TimeStamp Lifetime;
  415. SecBufferDesc OutBuffDesc;
  416. SecBuffer OutSecBuff;
  417. SecBufferDesc InBuffDesc;
  418. SecBuffer InSecBuff;
  419. ULONG ContextAttributes;
  420. if (NTLM_NO_INIT_CONTEXT == pAS->m_Conversation)
  421. {
  422. ss = g_pVars->m_pNTLMFuncs->AcquireCredentialsHandle (
  423. NULL, // principal
  424. NTLM_PACKAGE_NAME,
  425. SECPKG_CRED_OUTBOUND,
  426. NULL, // LOGON id
  427. pAuthIdentity, // auth data
  428. NULL, // get key fn
  429. NULL, // get key arg
  430. &pAS->m_hcred,
  431. &Lifetime
  432. );
  433. if (SEC_SUCCESS (ss))
  434. pAS->m_fHaveCredHandle = TRUE;
  435. else
  436. {
  437. TraceTag(ttidWebServer, "AcquireCreds failed: %X", ss);
  438. return(FALSE);
  439. }
  440. }
  441. // prepare output buffer
  442. //
  443. OutBuffDesc.ulVersion = 0;
  444. OutBuffDesc.cBuffers = 1;
  445. OutBuffDesc.pBuffers = &OutSecBuff;
  446. OutSecBuff.cbBuffer = *pcbOut;
  447. OutSecBuff.BufferType = SECBUFFER_TOKEN;
  448. OutSecBuff.pvBuffer = pOut;
  449. // prepare input buffer
  450. if (NTLM_NO_INIT_CONTEXT != pAS->m_Conversation)
  451. {
  452. InBuffDesc.ulVersion = 0;
  453. InBuffDesc.cBuffers = 1;
  454. InBuffDesc.pBuffers = &InSecBuff;
  455. InSecBuff.cbBuffer = cbIn;
  456. InSecBuff.BufferType = SECBUFFER_TOKEN;
  457. InSecBuff.pvBuffer = pIn;
  458. }
  459. ss = g_pVars->m_pNTLMFuncs->InitializeSecurityContext (
  460. &pAS->m_hcred,
  461. (pAS->m_Conversation == NTLM_PROCESSING) ? &pAS->m_hctxt : NULL,
  462. NULL,
  463. 0, // context requirements
  464. 0, // reserved1
  465. SECURITY_NATIVE_DREP,
  466. (pAS->m_Conversation == NTLM_PROCESSING) ? &InBuffDesc : NULL,
  467. 0, // reserved2
  468. &pAS->m_hctxt,
  469. &OutBuffDesc,
  470. &ContextAttributes,
  471. &Lifetime
  472. );
  473. if (!SEC_SUCCESS (ss))
  474. {
  475. TraceTag(ttidWebServer, "init context failed: %X", ss);
  476. return FALSE;
  477. }
  478. pAS->m_fHaveCtxtHandle = TRUE;
  479. // Complete token -- if applicable
  480. //
  481. if ((SEC_I_COMPLETE_NEEDED == ss) || (SEC_I_COMPLETE_AND_CONTINUE == ss))
  482. {
  483. if (g_pVars->m_pNTLMFuncs->CompleteAuthToken)
  484. {
  485. ss = g_pVars->m_pNTLMFuncs->CompleteAuthToken (&pAS->m_hctxt, &OutBuffDesc);
  486. if (!SEC_SUCCESS(ss))
  487. {
  488. TraceTag(ttidWebServer, "complete failed: %X", ss);
  489. return FALSE;
  490. }
  491. }
  492. else
  493. {
  494. TraceTag(ttidWebServer, "Complete not supported.");
  495. return FALSE;
  496. }
  497. }
  498. *pcbOut = OutSecBuff.cbBuffer;
  499. pAS->m_Conversation = NTLM_PROCESSING;
  500. return TRUE;
  501. }
  502. #endif // OLD_CE_BUILD
  503. // Called after a user has been successfully authenticated with either BASIC or NTLM.
  504. // See \winceos\comm\security\authhlp to see ACL algorithm function/description.
  505. // Our algorithm: AdminUsers reg value is set and user is a member, always grant
  506. // Admin auth. If no AdminUser key is set always grant Admin auth level,
  507. // UNLESS this vroot has a UserList set. If user is a member, then grant
  508. // ADMIN_USER, otherwise set to AUTH_PUBLIC (no auth).
  509. // If user is not in admin list but in UserList for vroot, grant AUTH_USER.
  510. AUTHLEVEL GetAuthFromACL(PAUTH_NTLM pAuth, PWSTR wszUser, PWSTR wszVRootUserList)
  511. {
  512. AUTHLEVEL AuthGranted = AUTH_USER;
  513. PWSTR wsz = NULL; // User (in function)
  514. PWSTR wszGroup = NULL;
  515. SecPkgContext_Names pkgName;
  516. #if defined(UNDER_CE) && !defined (OLD_CE_BUILD)
  517. SecPkgContext_GroupNames ContextGroups;
  518. ContextGroups.msGroupNames = NULL;
  519. #endif
  520. pkgName.sUserName = NULL;
  521. // If we're called from NTLM request (pAuth != NULL) then we need
  522. // to get the user name if we don't have it. On BASIC request, we
  523. // have wszUser name already.
  524. if (pAuth && !wszUser)
  525. {
  526. if ( SEC_SUCCESS(g_pVars->m_pNTLMFuncs->QueryContextAttributes(&(pAuth->m_hctxt),
  527. SECPKG_ATTR_NAMES, &pkgName)))
  528. {
  529. wsz = pkgName.sUserName;
  530. }
  531. else
  532. goto done; // If we can't get user name, don't bother continuing
  533. }
  534. else
  535. {
  536. wsz = wszUser;
  537. }
  538. #if defined(UNDER_CE) && !defined (OLD_CE_BUILD)
  539. if (pAuth)
  540. g_pVars->m_pNTLMFuncs->QueryContextAttributes(&(pAuth->m_hctxt),SECPKG_ATTR_GROUP_NAMES,&ContextGroups);
  541. wszGroup = ContextGroups.msGroupNames;
  542. #endif
  543. TraceTag(ttidWebServer, "ADmin Users = %s, wsz = %s, pkgName.sUserName = %s, group name = %s\r\n",
  544. g_pVars->m_wszAdminUsers,wsz,pkgName.sUserName,wszGroup);
  545. // Administrators always get admin access and access to the page, even if
  546. // they're barred in the VRoot list. If there is a vroot list and we fail
  547. // the IsAccessAllowed test, we set the auth granted to 0 - this
  548. // will deny access. If no VRoot user list is set, keep us at AUTH_USER.
  549. if ( !g_pVars->m_wszAdminUsers && !wszVRootUserList)
  550. AuthGranted = AUTH_ADMIN;
  551. else if (g_pVars->m_wszAdminUsers && IsAccessAllowed(wsz,wszGroup,g_pVars->m_wszAdminUsers,FALSE))
  552. AuthGranted = AUTH_ADMIN;
  553. else if (wszVRootUserList && IsAccessAllowed(wsz,wszGroup,wszVRootUserList,FALSE))
  554. {
  555. // If there is no Admin list set, grant admin
  556. if (!g_pVars->m_wszAdminUsers)
  557. AuthGranted = AUTH_ADMIN;
  558. else
  559. AuthGranted = AUTH_USER;
  560. }
  561. else if (wszVRootUserList)
  562. AuthGranted = AUTH_PUBLIC;
  563. done:
  564. if (pkgName.sUserName)
  565. g_pVars->m_pNTLMFuncs->FreeContextBuffer(pkgName.sUserName);
  566. #if defined(UNDER_CE) && !defined (OLD_CE_BUILD)
  567. if (ContextGroups.msGroupNames)
  568. g_pVars->m_pNTLMFuncs->FreeContextBuffer(ContextGroups.msGroupNames);
  569. #endif
  570. TraceTag(ttidWebServer, "HTTPD: GetAuthFromACL Admin Priveleges granted = %d",AuthGranted);
  571. return AuthGranted;
  572. }