From 674aa49910b4b2ce76c06fb3be7dddd7c180e619 Mon Sep 17 00:00:00 2001 From: Brandon Sterne Date: Sat, 10 Apr 2010 16:08:21 -0400 Subject: [PATCH] Bug 515797: Allow necko to create channels that are aware of Content Security Policy. r=jduell, sr=biesi --- content/base/src/Makefile.in | 1 + content/base/src/nsChannelPolicy.cpp | 76 +++++++++++++++++++++++ content/base/src/nsChannelPolicy.h | 67 ++++++++++++++++++++ layout/build/nsLayoutModule.cpp | 9 ++- netwerk/base/public/Makefile.in | 1 + netwerk/base/public/nsChannelProperties.h | 10 +++ netwerk/base/public/nsIChannelPolicy.idl | 60 ++++++++++++++++++ netwerk/base/public/nsNetStrings.h | 1 + netwerk/base/public/nsNetUtil.h | 14 ++++- netwerk/base/src/nsNetStrings.cpp | 3 +- 10 files changed, 238 insertions(+), 4 deletions(-) create mode 100644 content/base/src/nsChannelPolicy.cpp create mode 100644 content/base/src/nsChannelPolicy.h create mode 100644 netwerk/base/public/nsIChannelPolicy.idl diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in index 8fb0b12d6b6..133d9f97f04 100644 --- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -76,6 +76,7 @@ CPPSRCS = \ nsAttrAndChildArray.cpp \ nsAttrValue.cpp \ nsCCUncollectableMarker.cpp \ + nsChannelPolicy.cpp \ nsCommentNode.cpp \ nsContentAreaDragDrop.cpp \ nsContentIterator.cpp \ diff --git a/content/base/src/nsChannelPolicy.cpp b/content/base/src/nsChannelPolicy.cpp new file mode 100644 index 00000000000..63525e40d5f --- /dev/null +++ b/content/base/src/nsChannelPolicy.cpp @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code channel policy container code. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation + * + * Contributor(s): + * Brandon Sterne + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsChannelPolicy.h" + +nsChannelPolicy::nsChannelPolicy() +{ +} + +nsChannelPolicy::~nsChannelPolicy() +{ +} + +NS_IMPL_ISUPPORTS1(nsChannelPolicy, nsIChannelPolicy) + +NS_IMETHODIMP +nsChannelPolicy::GetLoadType(PRUint32 *aLoadType) +{ + *aLoadType = mLoadType; + return NS_OK; +} + +NS_IMETHODIMP +nsChannelPolicy::SetLoadType(PRUint32 aLoadType) +{ + mLoadType = aLoadType; + return NS_OK; +} + +NS_IMETHODIMP +nsChannelPolicy::GetContentSecurityPolicy(nsISupports **aCSP) +{ + *aCSP = mCSP; + NS_IF_ADDREF(*aCSP); + return NS_OK; +} + +NS_IMETHODIMP +nsChannelPolicy::SetContentSecurityPolicy(nsISupports *aCSP) +{ + mCSP = aCSP; + return NS_OK; +} diff --git a/content/base/src/nsChannelPolicy.h b/content/base/src/nsChannelPolicy.h new file mode 100644 index 00000000000..3e350d29a87 --- /dev/null +++ b/content/base/src/nsChannelPolicy.h @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code channel policy container code. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation + * + * Contributor(s): + * Brandon Sterne + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsChannelPolicy_h___ +#define nsChannelPolicy_h___ + +#include "nsCOMPtr.h" +#include "nsIChannelPolicy.h" + +#define NSCHANNELPOLICY_CONTRACTID "@mozilla.org/nschannelpolicy;1" +#define NSCHANNELPOLICY_CID \ +{ 0xd396b3cd, 0xf164, 0x4ce8, \ + { 0x93, 0xa7, 0xe3, 0x85, 0xe1, 0x46, 0x56, 0x3c } } + +class nsChannelPolicy : public nsIChannelPolicy +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSICHANNELPOLICY + + nsChannelPolicy(); + virtual ~nsChannelPolicy(); + +protected: + /* Represents the type of content being loaded in the channel per + * nsIContentPolicy, e.g. TYPE_IMAGE, TYPE_SCRIPT + */ + unsigned long mLoadType; + + /* pointer to a Content Security Policy object if available */ + nsCOMPtr mCSP; +}; + +#endif /* nsChannelPolicy_h___ */ diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 4a1e5078df9..450d4d4ae10 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -106,6 +106,7 @@ #include "nsDOMParser.h" #include "nsDOMSerializer.h" #include "nsXMLHttpRequest.h" +#include "nsChannelPolicy.h" // view stuff #include "nsViewsCID.h" @@ -296,6 +297,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsFileDataProtocolHandler) NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMParser) NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDOMStorageManager, nsDOMStorageManager::GetInstance) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsChannelPolicy) //----------------------------------------------------------------------------- @@ -1518,7 +1520,12 @@ static const nsModuleComponentInfo gComponents[] = { { "Event Listener Service", NS_EVENTLISTENERSERVICE_CID, NS_EVENTLISTENERSERVICE_CONTRACTID, - CreateEventListenerService } + CreateEventListenerService }, + + { "Channel Policy", + NSCHANNELPOLICY_CID, + NSCHANNELPOLICY_CONTRACTID, + nsChannelPolicyConstructor } }; NS_IMPL_NSGETMODULE_WITH_CTOR(nsLayoutModule, gComponents, Initialize) diff --git a/netwerk/base/public/Makefile.in b/netwerk/base/public/Makefile.in index d4d08bc9b72..27e64e6548d 100644 --- a/netwerk/base/public/Makefile.in +++ b/netwerk/base/public/Makefile.in @@ -74,6 +74,7 @@ XPIDLSRCS = \ nsIAsyncStreamCopier.idl \ nsIBufferedStreams.idl \ nsICancelable.idl \ + nsIChannelPolicy.idl \ nsICryptoHash.idl \ nsICryptoHMAC.idl \ nsIDownloader.idl \ diff --git a/netwerk/base/public/nsChannelProperties.h b/netwerk/base/public/nsChannelProperties.h index f1036a6f4c3..afafd34818a 100644 --- a/netwerk/base/public/nsChannelProperties.h +++ b/netwerk/base/public/nsChannelProperties.h @@ -65,14 +65,24 @@ */ #define NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR "content-disposition" +/** + * Exists to allow content policy mechanism to function properly during channel + * redirects. Contains security contextual information about the load. + * Type: nsIChannelPolicy + */ +#define NS_CHANNEL_PROP_CHANNEL_POLICY_STR "channel-policy" + #ifdef IMPL_NS_NET #define NS_CHANNEL_PROP_CONTENT_LENGTH gNetStrings->kContentLength #define NS_CHANNEL_PROP_CONTENT_DISPOSITION gNetStrings->kContentDisposition +#define NS_CHANNEL_PROP_CHANNEL_POLICY gNetStrings->kChannelPolicy #else #define NS_CHANNEL_PROP_CONTENT_LENGTH \ NS_LITERAL_STRING(NS_CHANNEL_PROP_CONTENT_LENGTH_STR) #define NS_CHANNEL_PROP_CONTENT_DISPOSITION \ NS_LITERAL_STRING(NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR) +#define NS_CHANNEL_PROP_CHANNEL_POLICY \ + NS_LITERAL_STRING(NS_CHANNEL_PROP_CHANNEL_POLICY_STR) #endif #endif diff --git a/netwerk/base/public/nsIChannelPolicy.idl b/netwerk/base/public/nsIChannelPolicy.idl new file mode 100644 index 00000000000..8695a535e31 --- /dev/null +++ b/netwerk/base/public/nsIChannelPolicy.idl @@ -0,0 +1,60 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org channel policy container code. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation + * + * Contributor(s): + * Brandon Sterne + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +/** + * A container for policy information to be used during channel creation. + * + * This interface exists to allow the content policy mechanism to function + * properly during channel redirects. Channels can be created with this + * interface placed in the property bag and upon redirect, the interface can + * be transferred from the old channel to the new channel. + */ +[scriptable, uuid(18045e96-1afe-4162-837a-04691267158c)] +interface nsIChannelPolicy : nsISupports +{ + /** + * Indicates what type of content is being loaded, e.g. + * nsIContentPolicy::TYPE_IMAGE + */ + attribute unsigned long loadType; + + /** + * A nsIContentSecurityPolicy object to determine if the load should + * be allowed. + */ + attribute nsISupports contentSecurityPolicy; +}; diff --git a/netwerk/base/public/nsNetStrings.h b/netwerk/base/public/nsNetStrings.h index 44d63a77e8e..09d874fda40 100644 --- a/netwerk/base/public/nsNetStrings.h +++ b/netwerk/base/public/nsNetStrings.h @@ -50,6 +50,7 @@ public: /** "content-length" */ const nsLiteralString kContentLength; const nsLiteralString kContentDisposition; + const nsLiteralString kChannelPolicy; }; extern NS_HIDDEN_(nsNetStrings*) gNetStrings; diff --git a/netwerk/base/public/nsNetUtil.h b/netwerk/base/public/nsNetUtil.h index a9fdda4934b..21d12dd4949 100644 --- a/netwerk/base/public/nsNetUtil.h +++ b/netwerk/base/public/nsNetUtil.h @@ -97,8 +97,10 @@ #include "nsINestedURI.h" #include "nsIMutable.h" #include "nsIPropertyBag2.h" +#include "nsIWritablePropertyBag2.h" #include "nsIIDNService.h" #include "nsIChannelEventSink.h" +#include "nsIChannelPolicy.h" // Helper, to simplify getting the I/O service. inline const nsGetServiceByContractIDWithError @@ -167,12 +169,13 @@ NS_NewFileURI(nsIURI* *result, } inline nsresult -NS_NewChannel(nsIChannel **result, +NS_NewChannel(nsIChannel **result, nsIURI *uri, nsIIOService *ioService = nsnull, // pass in nsIIOService to optimize callers nsILoadGroup *loadGroup = nsnull, nsIInterfaceRequestor *callbacks = nsnull, - PRUint32 loadFlags = nsIRequest::LOAD_NORMAL) + PRUint32 loadFlags = nsIRequest::LOAD_NORMAL, + nsIChannelPolicy *channelPolicy = nsnull) { nsresult rv; nsCOMPtr grip; @@ -187,6 +190,13 @@ NS_NewChannel(nsIChannel **result, rv |= chan->SetNotificationCallbacks(callbacks); if (loadFlags != nsIRequest::LOAD_NORMAL) rv |= chan->SetLoadFlags(loadFlags); + if (channelPolicy) { + nsCOMPtr props = do_QueryInterface(chan, &rv); + if (props) { + props->SetPropertyAsInterface(NS_CHANNEL_PROP_CHANNEL_POLICY, + channelPolicy); + } + } if (NS_SUCCEEDED(rv)) chan.forget(result); } diff --git a/netwerk/base/src/nsNetStrings.cpp b/netwerk/base/src/nsNetStrings.cpp index d28e9b96cb3..d7a8ee45072 100644 --- a/netwerk/base/src/nsNetStrings.cpp +++ b/netwerk/base/src/nsNetStrings.cpp @@ -41,7 +41,8 @@ NS_HIDDEN_(nsNetStrings*) gNetStrings; nsNetStrings::nsNetStrings() : NS_LITERAL_STRING_INIT(kContentLength, NS_CHANNEL_PROP_CONTENT_LENGTH_STR), - NS_LITERAL_STRING_INIT(kContentDisposition, NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR) + NS_LITERAL_STRING_INIT(kContentDisposition, NS_CHANNEL_PROP_CONTENT_DISPOSITION_STR), + NS_LITERAL_STRING_INIT(kChannelPolicy, NS_CHANNEL_PROP_CHANNEL_POLICY_STR) {}