diff --git a/mozilla/browser/locales/en-US/chrome/overrides/appstrings.properties b/mozilla/browser/locales/en-US/chrome/overrides/appstrings.properties index e70e7632de7..b1b2102ae55 100644 --- a/mozilla/browser/locales/en-US/chrome/overrides/appstrings.properties +++ b/mozilla/browser/locales/en-US/chrome/overrides/appstrings.properties @@ -53,6 +53,7 @@ deniedPortAccess=This address uses a network port which is normally used for pur proxyResolveFailure=Firefox is configured to use a proxy server that can't be found. proxyConnectFailure=Firefox is configured to use a proxy server that is refusing connections. contentEncodingError=The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression. Please contact the website owners to inform them of this problem. +unsafeContentType=The page you are trying to view cannot be shown because it is contained in a file type that may not be safe to open. Please contact the website owners to inform them of this problem. externalProtocolTitle=External Protocol Request externalProtocolPrompt=An external application must be launched to handle %1$S: links.\n\n\nRequested link:\n\n%2$S\n\nApplication: %3$S\n\n\nIf you were not expecting this request it may be an attempt to exploit a weakness in that other program. Cancel this request unless you are sure it is not malicious.\n #LOCALIZATION NOTE (externalProtocolUnknown): The following string is shown if the application name can't be determined diff --git a/mozilla/browser/locales/en-US/chrome/overrides/netError.dtd b/mozilla/browser/locales/en-US/chrome/overrides/netError.dtd index cc93b972d97..60d0e47584f 100644 --- a/mozilla/browser/locales/en-US/chrome/overrides/netError.dtd +++ b/mozilla/browser/locales/en-US/chrome/overrides/netError.dtd @@ -66,6 +66,13 @@ "> + + +
  • Please contact the website owners to inform them of this problem.
  • + +"> + diff --git a/mozilla/docshell/base/Makefile.in b/mozilla/docshell/base/Makefile.in index 2bb71726630..7e4e1ac00b4 100644 --- a/mozilla/docshell/base/Makefile.in +++ b/mozilla/docshell/base/Makefile.in @@ -85,6 +85,7 @@ REQUIRES = xpcom \ windowwatcher \ imglib2 \ mimetype \ + jar \ $(NULL) SDK_XPIDLSRCS = \ diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 3233392e619..56b5006c9dd 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -168,6 +168,8 @@ #include "nsITextToSubURI.h" +#include "nsIJARChannel.h" + #include "prlog.h" #include "prmem.h" @@ -1300,12 +1302,37 @@ nsDocShell::SetDocumentCharsetInfo(nsIDocumentCharsetInfo * return NS_OK; } +NS_IMETHODIMP +nsDocShell::GetChannelIsUnsafe(PRBool *aUnsafe) +{ + *aUnsafe = PR_FALSE; + + nsCOMPtr channel; + GetCurrentDocumentChannel(getter_AddRefs(channel)); + if (!channel) { + return NS_OK; + } + + nsCOMPtr jarChannel = do_QueryInterface(channel); + if (!jarChannel) { + return NS_OK; + } + + return jarChannel->GetIsUnsafe(aUnsafe); +} + NS_IMETHODIMP nsDocShell::GetAllowPlugins(PRBool * aAllowPlugins) { NS_ENSURE_ARG_POINTER(aAllowPlugins); *aAllowPlugins = mAllowPlugins; + if (!mAllowPlugins) { + return NS_OK; + } + + PRBool unsafe; + *aAllowPlugins = NS_SUCCEEDED(GetChannelIsUnsafe(&unsafe)) && !unsafe; return NS_OK; } @@ -1323,6 +1350,12 @@ nsDocShell::GetAllowJavascript(PRBool * aAllowJavascript) NS_ENSURE_ARG_POINTER(aAllowJavascript); *aAllowJavascript = mAllowJavascript; + if (!mAllowJavascript) { + return NS_OK; + } + + PRBool unsafe; + *aAllowJavascript = NS_SUCCEEDED(GetChannelIsUnsafe(&unsafe)) && !unsafe; return NS_OK; } @@ -1338,6 +1371,12 @@ NS_IMETHODIMP nsDocShell::GetAllowMetaRedirects(PRBool * aReturn) NS_ENSURE_ARG_POINTER(aReturn); *aReturn = mAllowMetaRedirects; + if (!mAllowMetaRedirects) { + return NS_OK; + } + + PRBool unsafe; + *aReturn = NS_SUCCEEDED(GetChannelIsUnsafe(&unsafe)) && !unsafe; return NS_OK; } @@ -3036,6 +3075,10 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI, // Bad Content Encoding. error.AssignLiteral("contentEncodingError"); break; + case NS_ERROR_UNSAFE_CONTENT_TYPE: + // Channel refused to load from an unrecognized content type. + error.AssignLiteral("unsafeContentType"); + break; } } @@ -6553,6 +6596,25 @@ nsDocShell::InternalLoad(nsIURI * aURI, (aFlags & INTERNAL_LOAD_FLAGS_INHERIT_OWNER) && NS_SUCCEEDED(URIInheritsSecurityContext(aURI, &inherits)) && inherits) { + + // Don't allow loads that would inherit our security context + // if this document came from an unsafe channel. + nsCOMPtr treeItem = this; + do { + nsCOMPtr itemDocShell = + do_QueryInterface(treeItem); + PRBool isUnsafe; + if (itemDocShell && + NS_SUCCEEDED(itemDocShell->GetChannelIsUnsafe(&isUnsafe)) && + isUnsafe) { + return NS_ERROR_DOM_SECURITY_ERR; + } + + nsCOMPtr parent; + treeItem->GetSameTypeParent(getter_AddRefs(parent)); + parent.swap(treeItem); + } while (treeItem); + owner = GetInheritedPrincipal(PR_TRUE); } } diff --git a/mozilla/docshell/base/nsIDocShell.idl b/mozilla/docshell/base/nsIDocShell.idl index 86a2935211f..b6d8205b681 100644 --- a/mozilla/docshell/base/nsIDocShell.idl +++ b/mozilla/docshell/base/nsIDocShell.idl @@ -68,7 +68,7 @@ interface nsILayoutHistoryState; interface nsISecureBrowserUI; interface nsIDOMStorage; -[scriptable, uuid(10ed386d-8598-408c-b571-e75ad18edeb0)] +[scriptable, uuid(4b00222a-8d0a-46d7-a1fe-43bd89d19324)] interface nsIDocShell : nsISupports { /** @@ -448,5 +448,12 @@ interface nsIDocShell : nsISupports * document has been set up) */ readonly attribute boolean isInUnload; + + /** + * Find out if the currently loaded document came from a suspicious channel + * (such as a JAR channel where the server-returned content type isn't a + * known JAR type). + */ + readonly attribute boolean channelIsUnsafe; }; diff --git a/mozilla/docshell/base/nsWebShell.cpp b/mozilla/docshell/base/nsWebShell.cpp index c146c498fd9..937391e4b86 100644 --- a/mozilla/docshell/base/nsWebShell.cpp +++ b/mozilla/docshell/base/nsWebShell.cpp @@ -1196,6 +1196,7 @@ nsresult nsWebShell::EndPageLoad(nsIWebProgress *aProgress, aStatus == NS_ERROR_NET_RESET || aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI || + aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE || NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) { DisplayLoadError(aStatus, url, nsnull, channel); } diff --git a/mozilla/docshell/resources/content/netError.xhtml b/mozilla/docshell/resources/content/netError.xhtml index 3584d5927d4..ccee9cdd1dd 100644 --- a/mozilla/docshell/resources/content/netError.xhtml +++ b/mozilla/docshell/resources/content/netError.xhtml @@ -219,6 +219,7 @@

    &proxyResolveFailure.title;

    &proxyConnectFailure.title;

    &contentEncodingError.title;

    +

    &unsafeContentType.title;

    &nssFailure2.title;

    &nssBadCert.title;

    &malwareBlocked.title;

    @@ -240,6 +241,7 @@
    &proxyResolveFailure.longDesc;
    &proxyConnectFailure.longDesc;
    &contentEncodingError.longDesc;
    +
    &unsafeContentType.longDesc;
    &nssFailure2.longDesc;
    &nssBadCert.longDesc2;
    &malwareBlocked.longDesc;
    diff --git a/mozilla/docshell/test/Makefile.in b/mozilla/docshell/test/Makefile.in index e58d2dae601..745bc73a90f 100644 --- a/mozilla/docshell/test/Makefile.in +++ b/mozilla/docshell/test/Makefile.in @@ -54,6 +54,8 @@ include $(topsrcdir)/config/rules.mk _TEST_FILES = \ test_bug344861.html \ + test_bug369814.html \ + bug369814.zip \ test_bug384014.html \ test_bug387979.html \ test_bug404548.html \ diff --git a/mozilla/docshell/test/bug369814.zip b/mozilla/docshell/test/bug369814.zip new file mode 100644 index 00000000000..86b9c8c0964 Binary files /dev/null and b/mozilla/docshell/test/bug369814.zip differ diff --git a/mozilla/docshell/test/test_bug369814.html b/mozilla/docshell/test/test_bug369814.html new file mode 100644 index 00000000000..85a7b3bdb7a --- /dev/null +++ b/mozilla/docshell/test/test_bug369814.html @@ -0,0 +1,204 @@ + + + + + Test for Bug 369814 + + + + + + +Mozilla Bug 369814 + +

    + + + +

    +
    +
    + + + diff --git a/mozilla/dom/locales/en-US/chrome/appstrings.properties b/mozilla/dom/locales/en-US/chrome/appstrings.properties index 2efa1b8fed8..21b2f059293 100644 --- a/mozilla/dom/locales/en-US/chrome/appstrings.properties +++ b/mozilla/dom/locales/en-US/chrome/appstrings.properties @@ -53,6 +53,7 @@ deniedPortAccess=Access to the port number given has been disabled for security proxyResolveFailure=The proxy server you have configured could not be found. Please check your proxy settings and try again. proxyConnectFailure=The connection was refused when attempting to contact the proxy server you have configured. Please check your proxy settings and try again. contentEncodingError=The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression. Please contact the website owners to inform them of this problem. +unsafeContentType=The page you are trying to view cannot be shown because it is contained in a file type that may not be safe to open. Please contact the website owners to inform them of this problem. externalProtocolTitle=External Protocol Request externalProtocolPrompt=An external application must be launched to handle %1$S: links.\n\n\nRequested link:\n\n%2$S\n\nApplication: %3$S\n\n\nIf you were not expecting this request it may be an attempt to exploit a weakness in that other program. Cancel this request unless you are sure it is not malicious.\n #LOCALIZATION NOTE (externalProtocolUnknown): The following string is shown if the application name can't be determined diff --git a/mozilla/dom/locales/en-US/chrome/netError.dtd b/mozilla/dom/locales/en-US/chrome/netError.dtd index 43e27ea43f5..716be04837c 100644 --- a/mozilla/dom/locales/en-US/chrome/netError.dtd +++ b/mozilla/dom/locales/en-US/chrome/netError.dtd @@ -30,6 +30,13 @@ The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression.

    • Please contact the website owners to inform them of this problem.
    "> + + +
  • Please contact the website owners to inform them of this problem.
  • + +"> + The network link was interrupted while negotiating a connection. Please try again.

    "> diff --git a/mozilla/modules/libjar/nsIJARChannel.idl b/mozilla/modules/libjar/nsIJARChannel.idl index a234dabc493..ee4063bf8dd 100644 --- a/mozilla/modules/libjar/nsIJARChannel.idl +++ b/mozilla/modules/libjar/nsIJARChannel.idl @@ -37,7 +37,14 @@ #include "nsIChannel.idl" -[scriptable, uuid(c7e410d1-85f2-11d3-9f63-006008a6efe9)] +[scriptable, uuid(6e6cc56d-51eb-4299-a795-dcfd1229ab3d)] interface nsIJARChannel : nsIChannel { + /** + * Returns TRUE if the JAR file is not safe (if the content type reported + * by the server for a remote JAR is not of an expected type). Scripting, + * redirects, and plugins should be disabled when loading from this + * channel. + */ + readonly attribute boolean isUnsafe; }; diff --git a/mozilla/modules/libjar/nsJARChannel.cpp b/mozilla/modules/libjar/nsJARChannel.cpp index a4e1460d94c..d90fb127508 100644 --- a/mozilla/modules/libjar/nsJARChannel.cpp +++ b/mozilla/modules/libjar/nsJARChannel.cpp @@ -44,6 +44,8 @@ #include "nsNetUtil.h" #include "nsInt64.h" #include "nsEscape.h" +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" #include "nsIScriptSecurityManager.h" #include "nsIPrincipal.h" @@ -222,6 +224,7 @@ nsJARChannel::nsJARChannel() , mLoadFlags(LOAD_NORMAL) , mStatus(NS_OK) , mIsPending(PR_FALSE) + , mIsUnsafe(PR_TRUE) , mJarInput(nsnull) { #if defined(PR_LOGGING) @@ -323,6 +326,8 @@ nsJARChannel::EnsureJarInput(PRBool blocking) } if (mJarFile) { + mIsUnsafe = PR_FALSE; + // NOTE: we do not need to deal with mSecurityInfo here, // because we're loading from a local file rv = CreateJarInput(gJarHandler->JarCache()); @@ -337,7 +342,7 @@ nsJARChannel::EnsureJarInput(PRBool blocking) if (NS_SUCCEEDED(rv)) rv = NS_OpenURI(mDownloader, nsnull, mJarBaseURI, nsnull, mLoadGroup, mCallbacks, - mLoadFlags & ~LOAD_DOCUMENT_URI); + mLoadFlags & ~(LOAD_DOCUMENT_URI | LOAD_CALL_CONTENT_SNIFFERS)); } return rv; @@ -644,6 +649,9 @@ nsJARChannel::Open(nsIInputStream **stream) NS_ENSURE_TRUE(!mJarInput, NS_ERROR_IN_PROGRESS); NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); + mJarFile = nsnull; + mIsUnsafe = PR_TRUE; + nsresult rv = EnsureJarInput(PR_TRUE); if (NS_FAILED(rv)) return rv; @@ -666,6 +674,9 @@ nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx) NS_ENSURE_ARG_POINTER(listener); NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); + mJarFile = nsnull; + mIsUnsafe = PR_TRUE; + // Initialize mProgressSink NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink); @@ -690,6 +701,16 @@ nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx) return NS_OK; } +//----------------------------------------------------------------------------- +// nsIJARChannel +//----------------------------------------------------------------------------- +NS_IMETHODIMP +nsJARChannel::GetIsUnsafe(PRBool *isUnsafe) +{ + *isUnsafe = mIsUnsafe; + return NS_OK; +} + //----------------------------------------------------------------------------- // nsIDownloadObserver //----------------------------------------------------------------------------- @@ -729,6 +750,47 @@ nsJARChannel::OnDownloadComplete(nsIDownloader *downloader, } status = rv; } + + nsCOMPtr httpChannel(do_QueryInterface(channel)); + if (httpChannel) { + // We only want to run scripts if the server really intended to + // send us a JAR file. Check the server-supplied content type for + // a JAR type. + nsCAutoString header; + httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"), + header); + + nsCAutoString contentType; + nsCAutoString charset; + NS_ParseContentType(header, contentType, charset); + + mIsUnsafe = !contentType.EqualsLiteral("application/java-archive") && + !contentType.EqualsLiteral("application/x-jar"); + } else { + nsCOMPtr innerJARChannel(do_QueryInterface(channel)); + if (innerJARChannel) { + PRBool unsafe; + innerJARChannel->GetIsUnsafe(&unsafe); + mIsUnsafe = unsafe; + } + } + + // XXX: THIS IS TEMPORARY + //mIsUnsafe = PR_FALSE; + } + + if (mIsUnsafe) { + PRBool allowUnpack = PR_FALSE; + + nsCOMPtr prefs = + do_GetService(NS_PREFSERVICE_CONTRACTID); + if (prefs) { + prefs->GetBoolPref("network.jar.open-unsafe-types", &allowUnpack); + } + + if (!allowUnpack) { + status = NS_ERROR_UNSAFE_CONTENT_TYPE; + } } if (NS_SUCCEEDED(status)) { @@ -745,6 +807,7 @@ nsJARChannel::OnDownloadComplete(nsIDownloader *downloader, } if (NS_FAILED(status)) { + mStatus = status; OnStartRequest(nsnull, nsnull); OnStopRequest(nsnull, nsnull, status); } diff --git a/mozilla/modules/libjar/nsJARChannel.h b/mozilla/modules/libjar/nsJARChannel.h index a015c5d3d54..719b298099b 100644 --- a/mozilla/modules/libjar/nsJARChannel.h +++ b/mozilla/modules/libjar/nsJARChannel.h @@ -97,7 +97,8 @@ private: PRInt32 mContentLength; PRUint32 mLoadFlags; nsresult mStatus; - PRBool mIsPending; + PRPackedBool mIsPending; + PRPackedBool mIsUnsafe; nsJARInputThunk *mJarInput; nsCOMPtr mDownloader; diff --git a/mozilla/modules/libpref/src/init/all.js b/mozilla/modules/libpref/src/init/all.js index 1f4751b509e..9c51c5389fe 100644 --- a/mozilla/modules/libpref/src/init/all.js +++ b/mozilla/modules/libpref/src/init/all.js @@ -613,6 +613,11 @@ pref("network.http.pipelining.maxrequests" , 4); // +// If false, remote JAR files that are served with a content type other than +// application/java-archive or application/x-jar will not be opened +// by the jar channel. +pref("network.jar.open-unsafe-types", false); + // This preference controls whether or not internationalized domain names (IDN) // are handled. IDN requires a nsIIDNService implementation. pref("network.enableIDN", true); diff --git a/mozilla/netwerk/base/public/nsNetError.h b/mozilla/netwerk/base/public/nsNetError.h index 65b15348866..f3f8bda3d48 100644 --- a/mozilla/netwerk/base/public/nsNetError.h +++ b/mozilla/netwerk/base/public/nsNetError.h @@ -232,6 +232,13 @@ #define NS_ERROR_REDIRECT_LOOP \ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 31) +/** + * The request failed because the content type returned by the server was + * not a type expected by the channel (for nested channels such as the JAR + * channel). + */ +#define NS_ERROR_UNSAFE_CONTENT_TYPE \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 74) /****************************************************************************** * FTP specific error codes: diff --git a/mozilla/testing/mochitest/tests/SimpleTest/EventUtils.js b/mozilla/testing/mochitest/tests/SimpleTest/EventUtils.js index 985255129c9..2a13d8d7d90 100644 --- a/mozilla/testing/mochitest/tests/SimpleTest/EventUtils.js +++ b/mozilla/testing/mochitest/tests/SimpleTest/EventUtils.js @@ -15,20 +15,24 @@ * * sendMouseEvent({type:'click'}, 'node'); */ -function sendMouseEvent(aEvent, aTarget) { +function sendMouseEvent(aEvent, aTarget, aWindow) { if (['click', 'mousedown', 'mouseup', 'mouseover', 'mouseout'].indexOf(aEvent.type) == -1) { throw new Error("sendMouseEvent doesn't know about event type '"+aEvent.type+"'"); } + if (!aWindow) { + aWindow = window; + } + // For events to trigger the UA's default actions they need to be "trusted" netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserWrite'); - var event = document.createEvent('MouseEvent'); + var event = aWindow.document.createEvent('MouseEvent'); var typeArg = aEvent.type; var canBubbleArg = true; var cancelableArg = true; - var viewArg = window; + var viewArg = aWindow; var detailArg = aEvent.detail || (aEvent.type == 'click' || aEvent.type == 'mousedown' || aEvent.type == 'mouseup' ? 1 : 0); @@ -48,7 +52,7 @@ function sendMouseEvent(aEvent, aTarget) { ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg, buttonArg, relatedTargetArg); - document.getElementById(aTarget).dispatchEvent(event); + aWindow.document.getElementById(aTarget).dispatchEvent(event); } /**