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.

294 lines
11 KiB

  1. /*****************************************************************************\
  2. FILE: security.cpp
  3. DESCRIPTION:
  4. Helpers functions to check if an Automation interface or ActiveX Control
  5. is hosted or used by a safe caller.
  6. BryanSt 8/25/1999
  7. Copyright (C) Microsoft Corp 1999-1999. All rights reserved.
  8. \*****************************************************************************/
  9. #include "stock.h"
  10. #pragma hdrstop
  11. #include <mshtml.h>
  12. /***************************************************************\
  13. DESCRIPTION:
  14. We are given a site via IObjectWithSite. Obtain the host
  15. from there.
  16. These are the different scenarios to test against:
  17. 1. HTA Content.
  18. 2. HTA contains IFRAME to non-LocalZone. That frame
  19. needs to be treated as unsafe because it hasn't been
  20. "sandboxed"
  21. 3. HTA contains IFRAME to non-LocalZone except the IFRAME tag has
  22. <IFRAME APPLICATION="Yes" SRC="non-LocalZone:foo.htm" ...>
  23. so we need to treat this as safe.
  24. 4. LocalZone Web page with Object. It has an IFRAME to an
  25. non-LocalZone. Is scripting from IFRAME to object allowed? [HUNTER?]
  26. 5. non-LocalZone Web page. It has an IFRAME to an LocalZone with Object.
  27. Is scripting from parent to IFRAME object allowed? [HUNTER?]
  28. 6. LocalZone Web page. It has 2 IFRAMEs. One is in the LocalZone and
  29. has an Object. The other is non-LocalZone. Can the non-LocalZone
  30. script across frames to the object? [HUNTER?]
  31. 7. VB or MFC host.
  32. 8. HTML Mail Message with object. This should be treated as
  33. non-LocalMachine? [HUNTER?]
  34. \***************************************************************/
  35. STDAPI GetHTMLDoc2(IUnknown *punk, IHTMLDocument2 **ppHtmlDoc)
  36. {
  37. *ppHtmlDoc = NULL;
  38. if (!punk)
  39. return E_FAIL;
  40. *ppHtmlDoc = NULL;
  41. // The window.external, jscript "new ActiveXObject" and the <OBJECT> tag
  42. // don't take us down the same road.
  43. IOleClientSite *pClientSite;
  44. HRESULT hr = punk->QueryInterface(IID_PPV_ARG(IOleClientSite, &pClientSite));
  45. if (SUCCEEDED(hr))
  46. {
  47. // <OBJECT> tag path
  48. IOleContainer *pContainer;
  49. // This will return the interface for the current FRAME containing the
  50. // OBJECT tag. We will only check that frames security because we
  51. // rely on MSHTML to block cross frame scripting when it isn't safe.
  52. hr = pClientSite->GetContainer(&pContainer);
  53. if (SUCCEEDED(hr))
  54. {
  55. hr = pContainer->QueryInterface(IID_PPV_ARG(IHTMLDocument2, ppHtmlDoc));
  56. pContainer->Release();
  57. }
  58. if (FAILED(hr))
  59. {
  60. // window.external path
  61. IWebBrowser2 *pWebBrowser2;
  62. hr = IUnknown_QueryService(pClientSite, SID_SWebBrowserApp, IID_PPV_ARG(IWebBrowser2, &pWebBrowser2));
  63. if (SUCCEEDED(hr))
  64. {
  65. IDispatch *pDispatch;
  66. hr = pWebBrowser2->get_Document(&pDispatch);
  67. if (SUCCEEDED(hr))
  68. {
  69. hr = pDispatch->QueryInterface(IID_PPV_ARG(IHTMLDocument2, ppHtmlDoc));
  70. pDispatch->Release();
  71. }
  72. pWebBrowser2->Release();
  73. }
  74. }
  75. pClientSite->Release();
  76. }
  77. else
  78. {
  79. // jscript path
  80. hr = IUnknown_QueryService(punk, SID_SContainerDispatch, IID_PPV_ARG(IHTMLDocument2, ppHtmlDoc));
  81. }
  82. ASSERT(FAILED(hr) || (*ppHtmlDoc));
  83. return hr;
  84. }
  85. /***************************************************************\
  86. DESCRIPTION:
  87. This function is supposed to find out the zone from the
  88. specified URL or Path.
  89. \***************************************************************/
  90. STDAPI LocalZoneCheckPath(LPCWSTR pszUrl, IUnknown * punkSite)
  91. {
  92. DWORD dwZoneID = URLZONE_UNTRUSTED;
  93. HRESULT hr = GetZoneFromUrl(pszUrl, punkSite, &dwZoneID);
  94. if (SUCCEEDED(hr))
  95. {
  96. if (dwZoneID == URLZONE_LOCAL_MACHINE)
  97. hr = S_OK;
  98. else
  99. hr = E_ACCESSDENIED;
  100. }
  101. return hr;
  102. }
  103. /***************************************************************\
  104. DESCRIPTION:
  105. Get the zone from the specified URL or Path.
  106. \***************************************************************/
  107. STDAPI GetZoneFromUrl(LPCWSTR pszUrl, IUnknown * punkSite, DWORD * pdwZoneID)
  108. {
  109. HRESULT hr = E_FAIL;
  110. if (pszUrl && pdwZoneID)
  111. {
  112. IInternetSecurityManager * pSecMgr = NULL;
  113. // WARNING: IInternetSecurityManager is the guy who translates
  114. // from URL->Zone. If we CoCreate this object, it will do the
  115. // default mapping. Some hosts, like Outlook Express, want to
  116. // over ride the default mapping in order to sandbox some content.
  117. // I beleive this could be used to force HTML in an email
  118. // message (C:\mailmessage.eml) to act like it's from a more
  119. // untrusted zone. We use QueryService to get this interface
  120. // from our host. This info is from SanjayS. (BryanSt 8/21/1999)
  121. hr = IUnknown_QueryService(punkSite, SID_SInternetSecurityManager, IID_PPV_ARG(IInternetSecurityManager, &pSecMgr));
  122. if (SUCCEEDED(hr))
  123. {
  124. hr = pSecMgr->MapUrlToZone(pszUrl, pdwZoneID, 0);
  125. ATOMICRELEASE(pSecMgr);
  126. }
  127. if (FAILED(hr))
  128. {
  129. hr = CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IInternetSecurityManager, &pSecMgr));
  130. if (SUCCEEDED(hr))
  131. {
  132. hr = pSecMgr->MapUrlToZone(pszUrl, pdwZoneID, 0);
  133. ATOMICRELEASE(pSecMgr);
  134. }
  135. }
  136. }
  137. else
  138. {
  139. hr = E_INVALIDARG;
  140. }
  141. return hr;
  142. }
  143. /***************************************************************\
  144. DESCRIPTION:
  145. We are given a site via IObjectWithSite. See if that host
  146. maps to the Local Zone.
  147. These are the different scenarios to test against:
  148. 1. HTA Content.
  149. 2. HTA contains IFRAME to non-LocalZone. That frame
  150. needs to be treated as unsafe because it hasn't been
  151. "sandboxed"
  152. 3. HTA contains IFRAME to non-LocalZone except the IFRAME tag has
  153. <IFRAME APPLICATION="Yes" SRC="non-LocalZone:foo.htm" ...>
  154. so we need to treat this as safe.
  155. 4. LocalZone Web page with Object. It has an IFRAME to an
  156. non-LocalZone. Is scripting from IFRAME to object allowed? [HUNTER?]
  157. 5. non-LocalZone Web page. It has an IFRAME to an LocalZone with Object.
  158. Is scripting from parent to IFRAME object allowed? [HUNTER?]
  159. 6. LocalZone Web page. It has 2 IFRAMEs. One is in the LocalZone and
  160. has an Object. The other is non-LocalZone. Can the non-LocalZone
  161. script across frames to the object? [HUNTER?]
  162. 7. VB or MFC host.
  163. 8. HTML Mail Message with object. This should be treated as
  164. non-LocalMachine? [HUNTER?]
  165. \***************************************************************/
  166. STDAPI LocalZoneCheck(IUnknown *punkSite)
  167. {
  168. DWORD dwZoneID = URLZONE_UNTRUSTED;
  169. HRESULT hr = GetZoneFromSite(punkSite, &dwZoneID);
  170. if (SUCCEEDED(hr))
  171. {
  172. if (dwZoneID == URLZONE_LOCAL_MACHINE)
  173. hr = S_OK;
  174. else
  175. hr = E_ACCESSDENIED;
  176. }
  177. return hr;
  178. }
  179. STDAPI GetZoneFromSite(IUnknown *punkSite, DWORD *pdwZoneID)
  180. {
  181. // Return S_FALSE if we don't have a host site since we have no way of doing a
  182. // security check. This is as far as VB 5.0 apps get.
  183. if (!punkSite)
  184. {
  185. *pdwZoneID = URLZONE_UNTRUSTED;
  186. return S_FALSE;
  187. }
  188. HRESULT hr = E_ACCESSDENIED;
  189. BOOL fTriedBrowser = FALSE;
  190. // Try to find the original template path for zone checking
  191. IOleCommandTarget * pct;
  192. if (SUCCEEDED(IUnknown_QueryService(punkSite, SID_DefView, IID_PPV_ARG(IOleCommandTarget, &pct))))
  193. {
  194. VARIANT vTemplatePath;
  195. vTemplatePath.vt = VT_EMPTY;
  196. if (pct->Exec(&CGID_DefView, DVCMDID_GETTEMPLATEDIRNAME, 0, NULL, &vTemplatePath) == S_OK)
  197. {
  198. fTriedBrowser = TRUE;
  199. if (vTemplatePath.vt == VT_BSTR)
  200. {
  201. hr = GetZoneFromUrl(vTemplatePath.bstrVal, punkSite, pdwZoneID);
  202. }
  203. // We were able to talk to the browser, so don't fall back on Trident because they may be
  204. // less secure.
  205. fTriedBrowser = TRUE;
  206. VariantClear(&vTemplatePath);
  207. }
  208. pct->Release();
  209. }
  210. // If this is one of those cases where the browser doesn't exist (AOL, VB, ...) then
  211. // we will check the scripts security. If we did ask the browser, don't ask trident
  212. // because the browser is often more restrictive in some cases.
  213. if (!fTriedBrowser && (hr != S_OK))
  214. {
  215. // Try to use the URL from the document to zone check
  216. IHTMLDocument2 *pHtmlDoc;
  217. /***************************************************************\
  218. NOTE:
  219. 1. If punkSite points into an <IFRAME APPLICATION="yes"> in a
  220. HTA file, then the URL GetHTMLDoc2() returns
  221. is for the IFRAME SRC..
  222. BUGS?:
  223. 1. If this isn't an HTML container, the we will be saying that it
  224. isn't safe. For example, if the container is VB and they support
  225. the security interfaces, then we will assume it isn't safe when
  226. it is. (Is there an IInternet interface that will work in this
  227. case?)
  228. \***************************************************************/
  229. if (SUCCEEDED(GetHTMLDoc2(punkSite, &pHtmlDoc)))
  230. {
  231. BSTR bstrURL;
  232. /***************************************************************\
  233. WARNING: (Security Holes?)
  234. I think this is fundamentally flawed because:
  235. 1. If this HTML container isn't safe but it's URL maps to the
  236. Local Zone, then we have a problem. This may happen with
  237. email messages, especially if they are saved to a file.
  238. If the user reopens a saved .eml file, it will be hosted in
  239. it's mail container that may support the IInternet interface
  240. to indicate that it's in an untrusted zone. Will we get
  241. a Local Zone URL in that case?
  242. TO INVESTIGATE: (HunterH?)
  243. 1. What is the parent HTML is LocalZone but the subframes aren't.
  244. Will trident block cross frame scripting?
  245. \***************************************************************/
  246. if (SUCCEEDED(pHtmlDoc->get_URL(&bstrURL)))
  247. {
  248. // NOTE: the above URL is improperly escaped, this is
  249. // due to app compat. if you depend on this URL being valid
  250. // use another means to get this
  251. hr = GetZoneFromUrl(bstrURL, punkSite, pdwZoneID);
  252. SysFreeString(bstrURL);
  253. }
  254. pHtmlDoc->Release();
  255. }
  256. }
  257. return hr;
  258. }