/*++ Copyright (c) 1997 Microsoft Corporation Module Name: urlzone.cxx Abstract: Glue layer to zone security manager, now residing in urlmon.dll Author: Rajeev Dujari (rajeevd) 02-Aug-1997 Contents: UrlZonesAttach UrlZonesDetach GetCredPolicy --*/ #include #include "urlmon.h" // // prototypes // typedef HRESULT (*PFNCREATESECMGR)(IServiceProvider * pSP, IInternetSecurityManager **ppSM, DWORD dwReserved); typedef HRESULT (*PFNCREATEZONEMGR)(IServiceProvider * pSP, IInternetZoneManager **ppZM, DWORD dwReserved); // // globals // IInternetSecurityManager* g_pSecMgr = NULL; IInternetZoneManager* g_pZoneMgr = NULL; static BOOL g_bAttemptedInit = FALSE; static HINSTANCE g_hInstUrlMon = NULL; static PFNCREATESECMGR g_pfnCreateSecMgr = NULL; static PFNCREATEZONEMGR g_pfnCreateZoneMgr = NULL; // // Handy class which uses a stack buffer if possible, otherwise allocates. // struct FlexBuf { BYTE Buf[512]; LPBYTE pbBuf; FlexBuf() { pbBuf = NULL; } ~FlexBuf() { if (pbBuf != NULL) { delete [] pbBuf; } } LPBYTE GetPtr (DWORD cbBuf) { if (cbBuf < sizeof(Buf)) return Buf; pbBuf = new BYTE [cbBuf]; return pbBuf; } }; struct UnicodeBuf : public FlexBuf { LPWSTR Convert (LPCSTR pszUrl) { DWORD cbUrl = lstrlenA (pszUrl) + 1; LPWSTR pwszUrl = (LPWSTR) GetPtr (sizeof(WCHAR) * cbUrl); if (!pwszUrl) return NULL; MultiByteToWideChar (CP_ACP, 0, pszUrl, cbUrl, pwszUrl, cbUrl); return pwszUrl; } }; // // Dynaload urlmon and create security manager object on demand. // BOOL UrlZonesAttach (void) { EnterCriticalSection(&ZoneMgrCritSec); BOOL bRet = FALSE; HRESULT hr; if (g_bAttemptedInit) { bRet = (g_pSecMgr != NULL && g_pZoneMgr != NULL); goto End; } g_bAttemptedInit = TRUE; g_hInstUrlMon = LoadLibraryA(URLMON_DLL); if (!g_hInstUrlMon) { bRet = FALSE; goto End; } g_pfnCreateSecMgr = (PFNCREATESECMGR) GetProcAddress(g_hInstUrlMon, "CoInternetCreateSecurityManager"); if (!g_pfnCreateSecMgr) { bRet = FALSE; goto End; } g_pfnCreateZoneMgr = (PFNCREATEZONEMGR) GetProcAddress(g_hInstUrlMon, "CoInternetCreateZoneManager"); if (!g_pfnCreateZoneMgr) { bRet = FALSE; goto End; } hr = (*g_pfnCreateSecMgr)(NULL, &g_pSecMgr, NULL); if( hr != S_OK ) { bRet = FALSE; goto End; } hr = (*g_pfnCreateZoneMgr)(NULL, &g_pZoneMgr, NULL); bRet = (hr == S_OK); End: LeaveCriticalSection(&ZoneMgrCritSec); return bRet; } // // Clean up upon process detach. // STDAPI_(void) UrlZonesDetach (void) { EnterCriticalSection(&ZoneMgrCritSec); if (g_pSecMgr) { g_pSecMgr->Release(); g_pSecMgr = NULL; } if (g_pZoneMgr) { g_pZoneMgr->Release(); g_pZoneMgr = NULL; } if (g_hInstUrlMon) { FreeLibrary(g_hInstUrlMon); g_hInstUrlMon = NULL; } LeaveCriticalSection(&ZoneMgrCritSec); } extern "C" DWORD GetZoneFromUrl(LPCSTR pszUrl); DWORD GetZoneFromUrl(LPCSTR pszUrl) { DWORD dwZone; dwZone = URLZONE_UNTRUSTED; // null URL indicates restricted zone. UnicodeBuf ub; EnterCriticalSection(&ZoneMgrCritSec); if (!g_pSecMgr && !UrlZonesAttach()) goto err; LPWSTR pwszUrl; if (!pszUrl) pwszUrl = NULL; else { pwszUrl = ub.Convert (pszUrl); if (!pwszUrl) goto err; } if (pszUrl) { // Otherwise determine the zone for this URL. g_pSecMgr->MapUrlToZone (pwszUrl, &dwZone, 0); } err: LeaveCriticalSection(&ZoneMgrCritSec); return dwZone; } // // Routine to get the Routine to indicate whether ntlm logon credential is allowed. // DWORD GetCredPolicy (LPSTR pszUrl) { HRESULT hr; DWORD dwPolicy; UnicodeBuf ub; EnterCriticalSection(&ZoneMgrCritSec); if (!UrlZonesAttach()) goto err; LPWSTR pwszUrl; if (!pszUrl) pwszUrl = NULL; else { pwszUrl = ub.Convert (pszUrl); if (!pwszUrl) goto err; } hr = g_pSecMgr->ProcessUrlAction (pwszUrl, URLACTION_CREDENTIALS_USE, (LPBYTE) &dwPolicy, sizeof(dwPolicy), NULL, 0, PUAF_NOUI, 0); // Resolve the ambiguous "Prompt if Intranet zone policy". if (dwPolicy == URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT) { DWORD dwZone; dwZone = URLZONE_UNTRUSTED; // null URL indicates restricted zone. if (pszUrl) { // Otherwise determine the zone for this URL. hr = g_pSecMgr->MapUrlToZone (pwszUrl, &dwZone, 0); if (hr != S_OK) goto err; } if (dwZone == URLZONE_INTRANET) dwPolicy = URLPOLICY_CREDENTIALS_SILENT_LOGON_OK; else dwPolicy = URLPOLICY_CREDENTIALS_MUST_PROMPT_USER; } LeaveCriticalSection(&ZoneMgrCritSec); return dwPolicy; err: INET_ASSERT (FALSE); LeaveCriticalSection(&ZoneMgrCritSec); return URLPOLICY_CREDENTIALS_MUST_PROMPT_USER; } /* Main-switch for the cookie feature has 3 states. 1. ALLOW: all cookies are accepted/replayed (including leashed ones) 2. QUERY: received cookies are subject to P3P evaluation, leashed cookies are not replayed 3. DISALLOW:no cookies are accepted/replayed. */ DWORD GetCookieMainSwitch(DWORD dwZone) { DWORD dwPolicy = URLPOLICY_DISALLOW; if (!UrlZonesAttach()) return dwPolicy; EnterCriticalSection(&ZoneMgrCritSec); HRESULT hr = g_pZoneMgr->GetZoneActionPolicy(dwZone, URLACTION_COOKIES_ENABLED, (LPBYTE)&dwPolicy, sizeof(dwPolicy), URLZONEREG_DEFAULT); LeaveCriticalSection(&ZoneMgrCritSec); return SUCCEEDED(hr) ? dwPolicy : URLPOLICY_ALLOW; } DWORD GetCookieMainSwitch(LPCSTR pszURL) { return GetCookieMainSwitch(GetZoneFromUrl(pszURL)); } DWORD GetCookiePolicy (LPCSTR pszUrl, DWORD dwUrlAction, BOOL fRestricted) { if (GlobalSuppressCookiesPolicy) { return URLPOLICY_ALLOW; } EnterCriticalSection(&ZoneMgrCritSec); UnicodeBuf ub; DWORD dwCP; if (!UrlZonesAttach()) goto err; // Convert to unicode. LPWSTR pwszUrl; pwszUrl = ub.Convert (pszUrl); if (!pwszUrl) goto err; DWORD dwPolicy; HRESULT hr; DWORD dwFlags; dwFlags = PUAF_NOUI; if (fRestricted) dwFlags |= PUAF_ENFORCERESTRICTED; hr = g_pSecMgr->ProcessUrlAction (pwszUrl, dwUrlAction, (LPBYTE) &dwPolicy, sizeof(dwPolicy), NULL, 0, dwFlags, 0); if (!SUCCEEDED(hr) ) goto err; dwCP = GetUrlPolicyPermissions(dwPolicy); LeaveCriticalSection(&ZoneMgrCritSec); return dwCP; err: LeaveCriticalSection(&ZoneMgrCritSec); INET_ASSERT (FALSE); return URLPOLICY_QUERY; } DWORD GetClientCertPromptPolicy (LPCSTR pszUrl, BOOL fRestricted /* = FALSE */) { EnterCriticalSection(&ZoneMgrCritSec); UnicodeBuf ub; DWORD dwCP; DWORD dwUrlAction = URLACTION_CLIENT_CERT_PROMPT; DWORD dwFlags; if (!UrlZonesAttach()) goto err; // Convert to unicode. LPWSTR pwszUrl; pwszUrl = ub.Convert (pszUrl); if (!pwszUrl) goto err; DWORD dwPolicy; dwFlags = PUAF_NOUI; if (fRestricted) dwFlags |= PUAF_ENFORCERESTRICTED; HRESULT hr; hr = g_pSecMgr->ProcessUrlAction (pwszUrl, dwUrlAction, (LPBYTE) &dwPolicy, sizeof(dwPolicy), NULL, 0, dwFlags, 0); if (!SUCCEEDED(hr) ) goto err; dwCP = GetUrlPolicyPermissions(dwPolicy); LeaveCriticalSection(&ZoneMgrCritSec); return dwCP; err: LeaveCriticalSection(&ZoneMgrCritSec); INET_ASSERT (FALSE); return URLPOLICY_QUERY; } VOID SetStopWarning( LPCSTR pszUrl, DWORD dwPolicy, DWORD dwUrlAction) { EnterCriticalSection(&ZoneMgrCritSec); UnicodeBuf ub; ZONEATTRIBUTES za = {0}; if (!UrlZonesAttach()) goto err; // Convert to unicode. LPWSTR pwszUrl; pwszUrl = ub.Convert (pszUrl); if (!pwszUrl) goto err; HRESULT hr; DWORD dwZone; hr = g_pSecMgr->MapUrlToZone(pwszUrl, &dwZone, 0); if (!SUCCEEDED(hr) ) goto err; DWORD dwZonePolicy; hr = g_pZoneMgr->GetZoneActionPolicy( dwZone, dwUrlAction, (LPBYTE)&dwZonePolicy, sizeof(dwZonePolicy), URLZONEREG_DEFAULT ); if (!SUCCEEDED(hr) ) goto err; // set the policy back with passed value SetUrlPolicyPermissions(dwZonePolicy, dwPolicy); hr = g_pZoneMgr->SetZoneActionPolicy( dwZone, dwUrlAction, (LPBYTE) &dwZonePolicy, sizeof(dwZonePolicy), URLZONEREG_DEFAULT ); if (!SUCCEEDED(hr) ) goto err; // change the generic zone setting to 'custom' now we've changed something za.cbSize = sizeof(ZONEATTRIBUTES); g_pZoneMgr->GetZoneAttributes(dwZone, &za); za.dwTemplateCurrentLevel = URLTEMPLATE_CUSTOM; g_pZoneMgr->SetZoneAttributes(dwZone, &za); err: LeaveCriticalSection(&ZoneMgrCritSec); return; } // // Set and query no cookies mode // BOOL IsNoCookies(DWORD dwZone) { BOOL fNoCookies = FALSE; HRESULT hr; DWORD dwZonePolicy; EnterCriticalSection(&ZoneMgrCritSec); if (!UrlZonesAttach()) goto exit; hr = g_pZoneMgr->GetZoneActionPolicy( dwZone, URLACTION_COOKIES_ENABLED, (LPBYTE)&dwZonePolicy, sizeof(dwZonePolicy), URLZONEREG_DEFAULT ); if(SUCCEEDED(hr)) { dwZonePolicy = GetUrlPolicyPermissions(dwZonePolicy); if(URLPOLICY_DISALLOW == dwZonePolicy) { fNoCookies = TRUE; } } exit: LeaveCriticalSection(&ZoneMgrCritSec); return fNoCookies; } void SetNoCookies(DWORD dwZone, DWORD dwNewPolicy) { DWORD dwZonePolicy; HRESULT hr; EnterCriticalSection(&ZoneMgrCritSec); if (!UrlZonesAttach()) goto exit; hr = g_pZoneMgr->GetZoneActionPolicy( dwZone, URLACTION_COOKIES_ENABLED, (LPBYTE)&dwZonePolicy, sizeof(dwZonePolicy), URLZONEREG_DEFAULT ); if(SUCCEEDED(hr)) { SetUrlPolicyPermissions(dwZonePolicy, dwNewPolicy); g_pZoneMgr->SetZoneActionPolicy( dwZone, URLACTION_COOKIES_ENABLED, (LPBYTE)&dwZonePolicy, sizeof(dwZonePolicy), URLZONEREG_DEFAULT ); } exit: LeaveCriticalSection(&ZoneMgrCritSec); }