Bug 523239 - CSP nsIChannelEventSink impl, r=jst, a=dholbert_sheriff

This commit is contained in:
Brandon Sterne 2010-04-23 10:03:03 -07:00
Родитель f3a84d4483
Коммит 0aac86c572
3 изменённых файлов: 121 добавлений и 13 удалений

Просмотреть файл

@ -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;
}