From 3d5f67908e8ccb2ec35297c50f7519972498ca26 Mon Sep 17 00:00:00 2001 From: "norris%netscape.com" Date: Wed, 23 Feb 2000 22:34:40 +0000 Subject: [PATCH] Fix 28612 META Refresh allowed in Mail/News r=mstoltz,a=jar Fix 28658 File upload vulnerability r=vidur,a=jar --- caps/idl/nsIScriptSecurityManager.idl | 75 ++++++++++++++++--- caps/src/nsScriptSecurityManager.cpp | 36 ++++----- content/base/src/nsGenericElement.cpp | 2 +- .../html/content/src/nsHTMLInputElement.cpp | 21 ++++++ .../html/document/src/nsHTMLContentSink.cpp | 5 +- content/xml/document/src/nsXMLContentSink.cpp | 2 +- dom/src/html/nsJSHTMLInputElement.cpp | 5 +- layout/base/src/nsGenericElement.cpp | 2 +- layout/generic/nsFrameFrame.cpp | 2 +- .../html/content/src/nsHTMLInputElement.cpp | 21 ++++++ layout/html/document/src/nsFrameFrame.cpp | 2 +- .../html/document/src/nsHTMLContentSink.cpp | 5 +- layout/html/forms/src/nsFormFrame.cpp | 3 +- layout/xml/document/src/nsXMLContentSink.cpp | 2 +- netwerk/protocol/http/src/nsHTTPChannel.cpp | 2 +- 15 files changed, 143 insertions(+), 42 deletions(-) diff --git a/caps/idl/nsIScriptSecurityManager.idl b/caps/idl/nsIScriptSecurityManager.idl index 965cb0c29eb..77cbf3df717 100644 --- a/caps/idl/nsIScriptSecurityManager.idl +++ b/caps/idl/nsIScriptSecurityManager.idl @@ -33,6 +33,34 @@ interface nsIURI; [uuid(58df5780-8006-11d2-bd91-00805f8ae3f4)] interface nsIScriptSecurityManager : nsISupports { + ///////////////// Principals /////////////////////// + + /** + * Return the principal of the innermost frame of the currently + * executing script. Will return null if there is no script + * currently executing. + */ + nsIPrincipal GetSubjectPrincipal(); + + /** + * Return the all-powerful system principal. + */ + nsIPrincipal GetSystemPrincipal(); + + /** + * Return a principal that can be QI'd to nsICodebasePrincipal and + * has the same origin as aURI. + */ + nsIPrincipal GetCodebasePrincipal(in nsIURI aURI); + + /** + * Return a principal that can be QI'd to nsICertificatePrincipal. + */ + nsIPrincipal GetCertificatePrincipal(in string aIssuer, in string aSerialNumber); + + + ///////////////// Security Checks ////////////////// + /** * Checks whether the currently executing script can access the given * property. @@ -50,6 +78,9 @@ interface nsIScriptSecurityManager : nsISupports * * Will return error code NS_ERROR_DOM_BAD_URI if the load request * should be denied. + * + * @param cx the JSContext of the script causing the load + * @param uri the URI that is being loaded */ void CheckLoadURIFromScript(in JSContextPtr cx, in nsIURI uri); @@ -58,33 +89,53 @@ interface nsIScriptSecurityManager : nsISupports * * Will return error code NS_ERROR_DOM_BAD_URI if the load request * should be denied. + * + * @param from the URI causing the load + * @param uri the URI that is being loaded + * @param disallowFromMail if true, return NS_ERROR_DOM_BAD_URI if 'from' + * is a URI associated with mail or news */ - void CheckLoadURI(in nsIURI from, in nsIURI uri); + void CheckLoadURI(in nsIURI from, in nsIURI uri, + in boolean disallowFromMail); /** - * Return the principal of the innermost frame of the currently - * executing script. Will return null if there is no script - * currently executing. + * Return true if content from the given principal is allowed to + * execute scripts. */ - nsIPrincipal GetSubjectPrincipal(); - - nsIPrincipal GetSystemPrincipal(); - - nsIPrincipal GetCodebasePrincipal(in nsIURI aURI); - boolean CanExecuteScripts(in nsIPrincipal principal); + /** + * Return true if the given JavaScript function was compiled with + * a principal that is allowed to execute scripts. + */ boolean CanExecuteFunction(in voidStar jsFunction); + + ///////////////// Capabilities ///////////////////// + + /** + * Return true if the currently executing script has 'capability' enabled. + */ boolean IsCapabilityEnabled(in string capability); + /** + * Enable 'capability' in the innermost frame of the currently executing + * script. + */ void EnableCapability(in string capability); + /** + * Remove 'capability' from the innermost frame of the currently executing + * script. Any setting of 'capability' from enclosing frames thus comes into + * effect. + */ void RevertCapability(in string capability); + /** + * Disable 'capability' in the innermost frame of the currently executing + * script. + */ void DisableCapability(in string capability); - - nsIPrincipal GetCertificatePrincipal(in string aIssuer, in string aSerialNumber); }; %{C++ diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index 48a03fb9616..e4e72d7619e 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -440,7 +440,7 @@ nsScriptSecurityManager::CheckLoadURIFromScript(JSContext *cx, nsCOMPtr uri; if (NS_FAILED(codebase->GetURI(getter_AddRefs(uri)))) return NS_ERROR_FAILURE; - if (NS_SUCCEEDED(CheckLoadURI(uri, aURI))) + if (NS_SUCCEEDED(CheckLoadURI(uri, aURI, PR_FALSE))) return NS_OK; // See if we're attempting to load a file: URI. If so, let a @@ -467,9 +467,21 @@ nsScriptSecurityManager::CheckLoadURIFromScript(JSContext *cx, } NS_IMETHODIMP -nsScriptSecurityManager::CheckLoadURI(nsIURI *aFromURI, - nsIURI *aURI) +nsScriptSecurityManager::CheckLoadURI(nsIURI *aFromURI, nsIURI *aURI, + PRBool aDisallowFromMail) { + nsXPIDLCString fromScheme; + if (NS_FAILED(aFromURI->GetScheme(getter_Copies(fromScheme)))) + return NS_ERROR_FAILURE; + + if (aDisallowFromMail && + (nsCRT::strcmp(fromScheme, "mailbox") == 0 || + nsCRT::strcmp(fromScheme, "imap") == 0 || + nsCRT::strcmp(fromScheme, "news"))) + { + return NS_ERROR_DOM_BAD_URI; + } + nsXPIDLCString scheme; if (NS_FAILED(aURI->GetScheme(getter_Copies(scheme)))) return NS_ERROR_FAILURE; @@ -485,9 +497,7 @@ nsScriptSecurityManager::CheckLoadURI(nsIURI *aFromURI, } nsXPIDLCString scheme2; - if (NS_SUCCEEDED(aFromURI->GetScheme(getter_Copies(scheme2))) && - nsCRT::strcmp(scheme, scheme2) == 0) - { + if (nsCRT::strcmp(scheme, fromScheme) == 0) { // every scheme can access another URI from the same scheme return NS_OK; } @@ -897,9 +907,9 @@ nsScriptSecurityManager::EnableCapability(const char *capability) source); Recycle(source); if (CheckConfirmDialog(message, check.GetUnicode(), &remember)) - canEnable = nsIPrincipal::ENABLE_GRANTED; - else - canEnable = nsIPrincipal::ENABLE_DENIED; + canEnable = nsIPrincipal::ENABLE_GRANTED; + else + canEnable = nsIPrincipal::ENABLE_DENIED; PR_FREEIF(message); if (remember) { if (NS_FAILED(principal->SetCanEnableCapability(capability, canEnable))) @@ -1138,14 +1148,6 @@ nsScriptSecurityManager::CheckPermissions(JSContext *aCx, JSObject *aObj, if (NS_FAILED(GetSubjectPrincipal(aCx, getter_AddRefs(subject)))) return NS_ERROR_FAILURE; - // If native code or system principal, allow access - PRBool equals; - if (!subject || - (NS_SUCCEEDED(subject->Equals(mSystemPrincipal, &equals)) && equals)) - { - return NS_OK; - } - nsCOMPtr object; if (NS_FAILED(GetObjectPrincipal(aCx, aObj, getter_AddRefs(object)))) return NS_ERROR_FAILURE; diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 8366792124b..2333d69bbdc 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -1520,7 +1520,7 @@ nsGenericElement::TriggerLink(nsIPresContext* aPresContext, if (NS_SUCCEEDED(rv)) rv = NS_NewURI(getter_AddRefs(absURI), absURLSpec, aBaseURL); if (NS_SUCCEEDED(rv)) - proceed = securityManager->CheckLoadURI(aBaseURL, absURI); + proceed = securityManager->CheckLoadURI(aBaseURL, absURI, PR_FALSE); // Only pass off the click event if the script security manager // says it's ok. diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 70b0444fc33..597101dc022 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -51,6 +51,9 @@ #include "nsIXBLBinding.h" #include "nsIEventStateManager.h" #include "nsISizeOfHandler.h" +#include "nsIServiceManager.h" +#include "nsIScriptSecurityManager.h" +#include "nsDOMError.h" #include "nsIPresState.h" #include "nsIDOMNodeList.h" @@ -453,6 +456,24 @@ nsHTMLInputElement::SetValue(const nsString& aValue) PRInt32 type; GetType(&type); if (NS_FORM_INPUT_TEXT == type || NS_FORM_INPUT_PASSWORD == type || NS_FORM_INPUT_FILE == type) { + if (NS_FORM_INPUT_FILE == type) { + nsresult result; + NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager, + NS_SCRIPTSECURITYMANAGER_PROGID, &result); + if (NS_FAILED(result)) + return result; + PRBool enabled; + if (NS_FAILED(result = securityManager->IsCapabilityEnabled("UniversalFileRead", + &enabled))) + { + return result; + } + if (!enabled) { + // setting the value of a "FILE" input widget requires the UniversalFileRead privilege + return NS_ERROR_DOM_SECURITY_ERR; + } + + } nsIFormControlFrame* formControlFrame = nsnull; if (NS_SUCCEEDED(nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame))) { if (nsnull != formControlFrame ) { diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index 1f49c0d0bb5..713ceb4c9a0 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -3788,7 +3788,8 @@ HTMLContentSink::ProcessMETATag(const nsIParserNode& aNode) NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager, NS_SCRIPTSECURITYMANAGER_PROGID, &rv); if (NS_SUCCEEDED(rv)) - rv = securityManager->CheckLoadURI(baseURI, uri); + rv = securityManager->CheckLoadURI(baseURI, uri, + PR_TRUE); } if (NS_FAILED(rv)) return rv; @@ -4247,7 +4248,7 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) NS_SCRIPTSECURITYMANAGER_PROGID, &rv); if (NS_FAILED(rv)) return rv; - rv = securityManager->CheckLoadURI(mDocumentBaseURL, url); + rv = securityManager->CheckLoadURI(mDocumentBaseURL, url, PR_FALSE); if (NS_FAILED(rv)) return rv; diff --git a/content/xml/document/src/nsXMLContentSink.cpp b/content/xml/document/src/nsXMLContentSink.cpp index 86dd7bee1da..38ac21642e4 100644 --- a/content/xml/document/src/nsXMLContentSink.cpp +++ b/content/xml/document/src/nsXMLContentSink.cpp @@ -1832,7 +1832,7 @@ nsXMLContentSink::ProcessStartSCRIPTTag(const nsIParserNode& aNode) NS_SCRIPTSECURITYMANAGER_PROGID, &rv); if (NS_FAILED(rv)) return rv; - rv = securityManager->CheckLoadURI(mDocumentBaseURL, url); + rv = securityManager->CheckLoadURI(mDocumentBaseURL, url, PR_FALSE); if (NS_FAILED(rv)) return rv; diff --git a/dom/src/html/nsJSHTMLInputElement.cpp b/dom/src/html/nsJSHTMLInputElement.cpp index 8d01892ee85..303a75e9356 100644 --- a/dom/src/html/nsJSHTMLInputElement.cpp +++ b/dom/src/html/nsJSHTMLInputElement.cpp @@ -658,7 +658,10 @@ SetHTMLInputElementProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) nsAutoString prop; nsJSUtils::nsConvertJSValToString(prop, cx, *vp); - a->SetSrc(prop); + rv = a->SetSrc(prop); + if (NS_FAILED(rv)) { + return nsJSUtils::nsReportError(cx, obj, rv); + } break; } diff --git a/layout/base/src/nsGenericElement.cpp b/layout/base/src/nsGenericElement.cpp index 8366792124b..2333d69bbdc 100644 --- a/layout/base/src/nsGenericElement.cpp +++ b/layout/base/src/nsGenericElement.cpp @@ -1520,7 +1520,7 @@ nsGenericElement::TriggerLink(nsIPresContext* aPresContext, if (NS_SUCCEEDED(rv)) rv = NS_NewURI(getter_AddRefs(absURI), absURLSpec, aBaseURL); if (NS_SUCCEEDED(rv)) - proceed = securityManager->CheckLoadURI(aBaseURL, absURI); + proceed = securityManager->CheckLoadURI(aBaseURL, absURI, PR_FALSE); // Only pass off the click event if the script security manager // says it's ok. diff --git a/layout/generic/nsFrameFrame.cpp b/layout/generic/nsFrameFrame.cpp index 54718bd52ac..df8d0c67add 100644 --- a/layout/generic/nsFrameFrame.cpp +++ b/layout/generic/nsFrameFrame.cpp @@ -895,7 +895,7 @@ nsHTMLFrameInnerFrame::Reflow(nsIPresContext* aPresContext, if (NS_SUCCEEDED(rv)) rv = NS_NewURI(getter_AddRefs(newURI), absURL, baseURI); if (NS_SUCCEEDED(rv)) - rv = securityManager->CheckLoadURI(baseURI, newURI); + rv = securityManager->CheckLoadURI(baseURI, newURI, PR_FALSE); if (NS_SUCCEEDED(rv)) { rv = mWebShell->LoadURL(absURL.GetUnicode()); // URL string with a default nsnull value for post Data diff --git a/layout/html/content/src/nsHTMLInputElement.cpp b/layout/html/content/src/nsHTMLInputElement.cpp index 70b0444fc33..597101dc022 100644 --- a/layout/html/content/src/nsHTMLInputElement.cpp +++ b/layout/html/content/src/nsHTMLInputElement.cpp @@ -51,6 +51,9 @@ #include "nsIXBLBinding.h" #include "nsIEventStateManager.h" #include "nsISizeOfHandler.h" +#include "nsIServiceManager.h" +#include "nsIScriptSecurityManager.h" +#include "nsDOMError.h" #include "nsIPresState.h" #include "nsIDOMNodeList.h" @@ -453,6 +456,24 @@ nsHTMLInputElement::SetValue(const nsString& aValue) PRInt32 type; GetType(&type); if (NS_FORM_INPUT_TEXT == type || NS_FORM_INPUT_PASSWORD == type || NS_FORM_INPUT_FILE == type) { + if (NS_FORM_INPUT_FILE == type) { + nsresult result; + NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager, + NS_SCRIPTSECURITYMANAGER_PROGID, &result); + if (NS_FAILED(result)) + return result; + PRBool enabled; + if (NS_FAILED(result = securityManager->IsCapabilityEnabled("UniversalFileRead", + &enabled))) + { + return result; + } + if (!enabled) { + // setting the value of a "FILE" input widget requires the UniversalFileRead privilege + return NS_ERROR_DOM_SECURITY_ERR; + } + + } nsIFormControlFrame* formControlFrame = nsnull; if (NS_SUCCEEDED(nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame))) { if (nsnull != formControlFrame ) { diff --git a/layout/html/document/src/nsFrameFrame.cpp b/layout/html/document/src/nsFrameFrame.cpp index 54718bd52ac..df8d0c67add 100644 --- a/layout/html/document/src/nsFrameFrame.cpp +++ b/layout/html/document/src/nsFrameFrame.cpp @@ -895,7 +895,7 @@ nsHTMLFrameInnerFrame::Reflow(nsIPresContext* aPresContext, if (NS_SUCCEEDED(rv)) rv = NS_NewURI(getter_AddRefs(newURI), absURL, baseURI); if (NS_SUCCEEDED(rv)) - rv = securityManager->CheckLoadURI(baseURI, newURI); + rv = securityManager->CheckLoadURI(baseURI, newURI, PR_FALSE); if (NS_SUCCEEDED(rv)) { rv = mWebShell->LoadURL(absURL.GetUnicode()); // URL string with a default nsnull value for post Data diff --git a/layout/html/document/src/nsHTMLContentSink.cpp b/layout/html/document/src/nsHTMLContentSink.cpp index 1f49c0d0bb5..713ceb4c9a0 100644 --- a/layout/html/document/src/nsHTMLContentSink.cpp +++ b/layout/html/document/src/nsHTMLContentSink.cpp @@ -3788,7 +3788,8 @@ HTMLContentSink::ProcessMETATag(const nsIParserNode& aNode) NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager, NS_SCRIPTSECURITYMANAGER_PROGID, &rv); if (NS_SUCCEEDED(rv)) - rv = securityManager->CheckLoadURI(baseURI, uri); + rv = securityManager->CheckLoadURI(baseURI, uri, + PR_TRUE); } if (NS_FAILED(rv)) return rv; @@ -4247,7 +4248,7 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode) NS_SCRIPTSECURITYMANAGER_PROGID, &rv); if (NS_FAILED(rv)) return rv; - rv = securityManager->CheckLoadURI(mDocumentBaseURL, url); + rv = securityManager->CheckLoadURI(mDocumentBaseURL, url, PR_FALSE); if (NS_FAILED(rv)) return rv; diff --git a/layout/html/forms/src/nsFormFrame.cpp b/layout/html/forms/src/nsFormFrame.cpp index be18b88381b..8ec82c46fb3 100644 --- a/layout/html/forms/src/nsFormFrame.cpp +++ b/layout/html/forms/src/nsFormFrame.cpp @@ -744,7 +744,8 @@ nsFormFrame::OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame) nsCOMPtr actionURL; if (NS_FAILED(result) || NS_FAILED(result = NS_NewURI(getter_AddRefs(actionURL), href, docURL)) || - NS_FAILED(result = securityManager->CheckLoadURI(docURL, actionURL))) + NS_FAILED(result = securityManager->CheckLoadURI(docURL, actionURL, + PR_FALSE))) { return result; } diff --git a/layout/xml/document/src/nsXMLContentSink.cpp b/layout/xml/document/src/nsXMLContentSink.cpp index 86dd7bee1da..38ac21642e4 100644 --- a/layout/xml/document/src/nsXMLContentSink.cpp +++ b/layout/xml/document/src/nsXMLContentSink.cpp @@ -1832,7 +1832,7 @@ nsXMLContentSink::ProcessStartSCRIPTTag(const nsIParserNode& aNode) NS_SCRIPTSECURITYMANAGER_PROGID, &rv); if (NS_FAILED(rv)) return rv; - rv = securityManager->CheckLoadURI(mDocumentBaseURL, url); + rv = securityManager->CheckLoadURI(mDocumentBaseURL, url, PR_FALSE); if (NS_FAILED(rv)) return rv; diff --git a/netwerk/protocol/http/src/nsHTTPChannel.cpp b/netwerk/protocol/http/src/nsHTTPChannel.cpp index 85845520106..5e08578b734 100644 --- a/netwerk/protocol/http/src/nsHTTPChannel.cpp +++ b/netwerk/protocol/http/src/nsHTTPChannel.cpp @@ -1278,7 +1278,7 @@ nsresult nsHTTPChannel::Redirect(const char *aNewLocation, NS_WITH_SERVICE(nsIScriptSecurityManager, securityManager, NS_SCRIPTSECURITYMANAGER_PROGID, &rv); if (NS_FAILED(rv)) return rv; - rv = securityManager->CheckLoadURI(mOriginalURI, newURI); + rv = securityManager->CheckLoadURI(mOriginalURI, newURI, PR_TRUE); if (NS_FAILED(rv)) return rv; rv = serv->NewChannelFromURI(mVerb.GetBuffer(), newURI, mLoadGroup,