зеркало из 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 "nsContentUtils.h"
|
||||||
#include "nsCSPService.h"
|
#include "nsCSPService.h"
|
||||||
#include "nsIContentSecurityPolicy.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 */
|
/* Keeps track of whether or not CSP is enabled */
|
||||||
static PRBool gCSPEnabled = PR_TRUE;
|
static PRBool gCSPEnabled = PR_TRUE;
|
||||||
|
@ -69,7 +75,7 @@ CSPService::~CSPService()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS1(CSPService, nsIContentPolicy)
|
NS_IMPL_ISUPPORTS2(CSPService, nsIContentPolicy, nsIChannelEventSink)
|
||||||
|
|
||||||
/* nsIContentPolicy implementation */
|
/* nsIContentPolicy implementation */
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -99,8 +105,8 @@ CSPService::ShouldLoad(PRUint32 aContentType,
|
||||||
if (!gCSPEnabled)
|
if (!gCSPEnabled)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
|
||||||
// find the nsDocument that initiated this request and see if it has a
|
// find the principal of the document that initiated this request and see
|
||||||
// CSP policy object
|
// if it has a CSP policy object
|
||||||
nsCOMPtr<nsINode> node(do_QueryInterface(aRequestContext));
|
nsCOMPtr<nsINode> node(do_QueryInterface(aRequestContext));
|
||||||
nsCOMPtr<nsIPrincipal> principal;
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
nsCOMPtr<nsIContentSecurityPolicy> csp;
|
||||||
|
@ -194,3 +200,87 @@ CSPService::ShouldProcess(PRUint32 aContentType,
|
||||||
#endif
|
#endif
|
||||||
return NS_OK;
|
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 "nsXPCOM.h"
|
||||||
#include "nsIContentPolicy.h"
|
#include "nsIContentPolicy.h"
|
||||||
|
#include "nsIChannel.h"
|
||||||
|
#include "nsIChannelEventSink.h"
|
||||||
|
|
||||||
#define CSPSERVICE_CONTRACTID "@mozilla.org/cspservice;1"
|
#define CSPSERVICE_CONTRACTID "@mozilla.org/cspservice;1"
|
||||||
#define CSPSERVICE_CID \
|
#define CSPSERVICE_CID \
|
||||||
{ 0x8d2f40b2, 0x4875, 0x4c95, \
|
{ 0x8d2f40b2, 0x4875, 0x4c95, \
|
||||||
{ 0x97, 0xd9, 0x3f, 0x7d, 0xca, 0x2c, 0xb4, 0x60 } }
|
{ 0x97, 0xd9, 0x3f, 0x7d, 0xca, 0x2c, 0xb4, 0x60 } }
|
||||||
class CSPService : public nsIContentPolicy
|
class CSPService : public nsIContentPolicy,
|
||||||
|
public nsIChannelEventSink
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
NS_DECL_NSICONTENTPOLICY
|
NS_DECL_NSICONTENTPOLICY
|
||||||
|
NS_DECL_NSICHANNELEVENTSINK
|
||||||
|
|
||||||
CSPService();
|
CSPService();
|
||||||
virtual ~CSPService();
|
virtual ~CSPService();
|
||||||
|
|
|
@ -875,6 +875,16 @@ CSPServiceRegistration(nsIComponentManager *aCompMgr,
|
||||||
PR_TRUE,
|
PR_TRUE,
|
||||||
PR_TRUE,
|
PR_TRUE,
|
||||||
getter_Copies(previous));
|
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;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,6 +908,10 @@ CSPServiceUnregistration(nsIComponentManager *aCompMgr,
|
||||||
"CSPService",
|
"CSPService",
|
||||||
PR_TRUE);
|
PR_TRUE);
|
||||||
|
|
||||||
|
rv = catman->DeleteCategoryEntry("net-channel-event-sinks",
|
||||||
|
"CSPService",
|
||||||
|
PR_TRUE);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче