зеркало из https://github.com/mozilla/gecko-dev.git
Bug 523239 - CSP nsIChannelEventSink impl, r=jst, a=dholbert_sheriff
This commit is contained in:
Родитель
f3a84d4483
Коммит
0aac86c572
|
@ -47,6 +47,12 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsCSPService.h"
|
||||
#include "nsIContentSecurityPolicy.h"
|
||||
#include "nsIChannelPolicy.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "nsIWritablePropertyBag2.h"
|
||||
#include "nsNetError.h"
|
||||
#include "nsChannelProperties.h"
|
||||
|
||||
/* Keeps track of whether or not CSP is enabled */
|
||||
static PRBool gCSPEnabled = PR_TRUE;
|
||||
|
@ -69,7 +75,7 @@ CSPService::~CSPService()
|
|||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CSPService, nsIContentPolicy)
|
||||
NS_IMPL_ISUPPORTS2(CSPService, nsIContentPolicy, nsIChannelEventSink)
|
||||
|
||||
/* nsIContentPolicy implementation */
|
||||
NS_IMETHODIMP
|
||||
|
@ -84,11 +90,11 @@ CSPService::ShouldLoad(PRUint32 aContentType,
|
|||
if (!aContentLocation)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
#ifdef PR_LOGGING
|
||||
{
|
||||
nsCAutoString location;
|
||||
aContentLocation->GetSpec(location);
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("CSPService::ShouldLoad called for %s", location.get()));
|
||||
}
|
||||
#endif
|
||||
|
@ -99,8 +105,8 @@ CSPService::ShouldLoad(PRUint32 aContentType,
|
|||
if (!gCSPEnabled)
|
||||
return NS_OK;
|
||||
|
||||
// find the nsDocument that initiated this request and see if it has a
|
||||
// CSP policy object
|
||||
// find the principal of the document that initiated this request and see
|
||||
// if it has a CSP policy object
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(aRequestContext));
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
|
@ -109,11 +115,11 @@ CSPService::ShouldLoad(PRUint32 aContentType,
|
|||
principal->GetCsp(getter_AddRefs(csp));
|
||||
|
||||
if (csp) {
|
||||
#ifdef PR_LOGGING
|
||||
#ifdef PR_LOGGING
|
||||
nsAutoString policy;
|
||||
csp->GetPolicy(policy);
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("Document has CSP: %s",
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("Document has CSP: %s",
|
||||
NS_ConvertUTF16toUTF8(policy).get()));
|
||||
#endif
|
||||
// obtain the enforcement decision
|
||||
|
@ -130,11 +136,11 @@ CSPService::ShouldLoad(PRUint32 aContentType,
|
|||
else {
|
||||
nsCAutoString uriSpec;
|
||||
aContentLocation->GetSpec(uriSpec);
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("COULD NOT get nsINode for location: %s", uriSpec.get()));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -170,7 +176,7 @@ CSPService::ShouldProcess(PRUint32 aContentType,
|
|||
#ifdef PR_LOGGING
|
||||
nsAutoString policy;
|
||||
csp->GetPolicy(policy);
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("shouldProcess - document has policy: %s",
|
||||
NS_ConvertUTF16toUTF8(policy).get()));
|
||||
#endif
|
||||
|
@ -188,9 +194,93 @@ CSPService::ShouldProcess(PRUint32 aContentType,
|
|||
else {
|
||||
nsCAutoString uriSpec;
|
||||
aContentLocation->GetSpec(uriSpec);
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("COULD NOT get nsINode for location: %s", uriSpec.get()));
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* nsIChannelEventSink implementation */
|
||||
NS_IMETHODIMP
|
||||
CSPService::OnChannelRedirect(nsIChannel *oldChannel,
|
||||
nsIChannel *newChannel,
|
||||
PRUint32 flags)
|
||||
{
|
||||
// get the Content Security Policy and load type from the property bag
|
||||
nsCOMPtr<nsISupports> policyContainer;
|
||||
nsCOMPtr<nsIPropertyBag2> props(do_QueryInterface(oldChannel));
|
||||
if (!props)
|
||||
return NS_OK;
|
||||
|
||||
props->GetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY,
|
||||
NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(policyContainer));
|
||||
|
||||
// see if we have a valid nsIChannelPolicy containing CSP and load type
|
||||
nsCOMPtr<nsIChannelPolicy> channelPolicy(do_QueryInterface(policyContainer));
|
||||
if (!channelPolicy)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||
channelPolicy->GetContentSecurityPolicy(getter_AddRefs(csp));
|
||||
PRUint32 loadType;
|
||||
channelPolicy->GetLoadType(&loadType);
|
||||
|
||||
// if no CSP in the channelPolicy, nothing for us to add to the channel
|
||||
if (!csp)
|
||||
return NS_OK;
|
||||
|
||||
/* Since redirecting channels don't call into nsIContentPolicy, we call our
|
||||
* Content Policy implementation directly when redirects occur. When channels
|
||||
* are created using NS_NewChannel(), callers can optionally pass in a
|
||||
* nsIChannelPolicy containing a CSP object and load type, which is placed in
|
||||
* the new channel's property bag. This container is propagated forward when
|
||||
* channels redirect.
|
||||
*/
|
||||
|
||||
// Does the CSP permit this host for this type of load?
|
||||
// If not, cancel the load now.
|
||||
nsCOMPtr<nsIURI> newUri;
|
||||
newChannel->GetURI(getter_AddRefs(newUri));
|
||||
PRInt16 aDecision = nsIContentPolicy::ACCEPT;
|
||||
csp->ShouldLoad(loadType, // load type per nsIContentPolicy (PRUint32)
|
||||
newUri, // nsIURI
|
||||
nsnull, // nsIURI
|
||||
nsnull, // nsISupports
|
||||
EmptyCString(), // ACString - MIME guess
|
||||
nsnull, // nsISupports - extra
|
||||
&aDecision);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (newUri) {
|
||||
nsCAutoString newUriSpec("None");
|
||||
newUri->GetSpec(newUriSpec);
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("CSPService::OnChannelRedirect called for %s", newUriSpec.get()));
|
||||
}
|
||||
if (aDecision == 1)
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("CSPService::OnChannelRedirect ALLOWING request."));
|
||||
else
|
||||
PR_LOG(gCspPRLog, PR_LOG_DEBUG,
|
||||
("CSPService::OnChannelRedirect CANCELLING request."));
|
||||
#endif
|
||||
|
||||
// if ShouldLoad doesn't accept the load, cancel the request
|
||||
if (aDecision != 1) {
|
||||
newChannel->Cancel(NS_BINDING_FAILED);
|
||||
}
|
||||
|
||||
else {
|
||||
// the redirect is permitted, so propagate the Content Security Policy
|
||||
// and load type to the redirecting channel
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWritablePropertyBag2> props = do_QueryInterface(newChannel, &rv);
|
||||
if (props)
|
||||
props->SetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY,
|
||||
channelPolicy);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -38,16 +38,20 @@
|
|||
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
|
||||
#define CSPSERVICE_CONTRACTID "@mozilla.org/cspservice;1"
|
||||
#define CSPSERVICE_CID \
|
||||
{ 0x8d2f40b2, 0x4875, 0x4c95, \
|
||||
{ 0x97, 0xd9, 0x3f, 0x7d, 0xca, 0x2c, 0xb4, 0x60 } }
|
||||
class CSPService : public nsIContentPolicy
|
||||
class CSPService : public nsIContentPolicy,
|
||||
public nsIChannelEventSink
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICONTENTPOLICY
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
CSPService();
|
||||
virtual ~CSPService();
|
||||
|
|
|
@ -875,6 +875,16 @@ CSPServiceRegistration(nsIComponentManager *aCompMgr,
|
|||
PR_TRUE,
|
||||
PR_TRUE,
|
||||
getter_Copies(previous));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = catman->AddCategoryEntry("net-channel-event-sinks",
|
||||
"CSPService",
|
||||
CSPSERVICE_CONTRACTID,
|
||||
PR_TRUE,
|
||||
PR_TRUE,
|
||||
getter_Copies(previous));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -898,6 +908,10 @@ CSPServiceUnregistration(nsIComponentManager *aCompMgr,
|
|||
"CSPService",
|
||||
PR_TRUE);
|
||||
|
||||
rv = catman->DeleteCategoryEntry("net-channel-event-sinks",
|
||||
"CSPService",
|
||||
PR_TRUE);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче