netwerk/protocol/about/nsAboutProtocolHandler.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "base/basictypes.h"
     8 #include "nsAboutProtocolHandler.h"
     9 #include "nsIURI.h"
    10 #include "nsIAboutModule.h"
    11 #include "nsString.h"
    12 #include "nsNetCID.h"
    13 #include "nsAboutProtocolUtils.h"
    14 #include "nsError.h"
    15 #include "nsNetUtil.h"
    16 #include "nsIObjectInputStream.h"
    17 #include "nsIObjectOutputStream.h"
    18 #include "nsAutoPtr.h"
    19 #include "nsIWritablePropertyBag2.h"
    21 static NS_DEFINE_CID(kSimpleURICID,     NS_SIMPLEURI_CID);
    22 static NS_DEFINE_CID(kNestedAboutURICID, NS_NESTEDABOUTURI_CID);
    24 static bool IsSafeForUntrustedContent(nsIAboutModule *aModule, nsIURI *aURI) {
    25   uint32_t flags;
    26   nsresult rv = aModule->GetURIFlags(aURI, &flags);
    27   NS_ENSURE_SUCCESS(rv, false);
    29   return (flags & nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT) != 0;
    30 }
    31 ////////////////////////////////////////////////////////////////////////////////
    33 NS_IMPL_ISUPPORTS(nsAboutProtocolHandler, nsIProtocolHandler)
    35 ////////////////////////////////////////////////////////////////////////////////
    36 // nsIProtocolHandler methods:
    38 NS_IMETHODIMP
    39 nsAboutProtocolHandler::GetScheme(nsACString &result)
    40 {
    41     result.AssignLiteral("about");
    42     return NS_OK;
    43 }
    45 NS_IMETHODIMP
    46 nsAboutProtocolHandler::GetDefaultPort(int32_t *result)
    47 {
    48     *result = -1;        // no port for about: URLs
    49     return NS_OK;
    50 }
    52 NS_IMETHODIMP
    53 nsAboutProtocolHandler::GetProtocolFlags(uint32_t *result)
    54 {
    55     *result = URI_NORELATIVE | URI_NOAUTH | URI_DANGEROUS_TO_LOAD;
    56     return NS_OK;
    57 }
    59 NS_IMETHODIMP
    60 nsAboutProtocolHandler::NewURI(const nsACString &aSpec,
    61                                const char *aCharset, // ignore charset info
    62                                nsIURI *aBaseURI,
    63                                nsIURI **result)
    64 {
    65     *result = nullptr;
    66     nsresult rv;
    68     // Use a simple URI to parse out some stuff first
    69     nsCOMPtr<nsIURI> url = do_CreateInstance(kSimpleURICID, &rv);
    70     if (NS_FAILED(rv)) return rv;
    72     rv = url->SetSpec(aSpec);
    73     if (NS_FAILED(rv)) {
    74         return rv;
    75     }
    77     // Unfortunately, people create random about: URIs that don't correspond to
    78     // about: modules...  Since those URIs will never open a channel, might as
    79     // well consider them unsafe for better perf, and just in case.
    80     bool isSafe = false;
    82     nsCOMPtr<nsIAboutModule> aboutMod;
    83     rv = NS_GetAboutModule(url, getter_AddRefs(aboutMod));
    84     if (NS_SUCCEEDED(rv)) {
    85         isSafe = IsSafeForUntrustedContent(aboutMod, url);
    86     }
    88     if (isSafe) {
    89         // We need to indicate that this baby is safe.  Use an inner URI that
    90         // no one but the security manager will see.  Make sure to preserve our
    91         // path, in case someone decides to hardcode checks for particular
    92         // about: URIs somewhere.
    93         nsAutoCString spec;
    94         rv = url->GetPath(spec);
    95         NS_ENSURE_SUCCESS(rv, rv);
    97         spec.Insert("moz-safe-about:", 0);
    99         nsCOMPtr<nsIURI> inner;
   100         rv = NS_NewURI(getter_AddRefs(inner), spec);
   101         NS_ENSURE_SUCCESS(rv, rv);
   103         nsSimpleNestedURI* outer = new nsNestedAboutURI(inner, aBaseURI);
   104         NS_ENSURE_TRUE(outer, NS_ERROR_OUT_OF_MEMORY);
   106         // Take a ref to it in the COMPtr we plan to return
   107         url = outer;
   109         rv = outer->SetSpec(aSpec);
   110         NS_ENSURE_SUCCESS(rv, rv);
   111     }
   113     // We don't want to allow mutation, since it would allow safe and
   114     // unsafe URIs to change into each other...
   115     NS_TryToSetImmutable(url);
   116     url.swap(*result);
   117     return NS_OK;
   118 }
   120 NS_IMETHODIMP
   121 nsAboutProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
   122 {
   123     NS_ENSURE_ARG_POINTER(uri);
   125     // about:what you ask?
   126     nsCOMPtr<nsIAboutModule> aboutMod;
   127     nsresult rv = NS_GetAboutModule(uri, getter_AddRefs(aboutMod));
   129     nsAutoCString path;
   130     nsresult rv2 = NS_GetAboutModuleName(uri, path);
   131     if (NS_SUCCEEDED(rv2) && path.EqualsLiteral("srcdoc")) {
   132         // about:srcdoc is meant to be unresolvable, yet is included in the 
   133         // about lookup tables so that it can pass security checks when used in
   134         // a srcdoc iframe.  To ensure that it stays unresolvable, we pretend
   135         // that it doesn't exist.
   136       rv = NS_ERROR_FACTORY_NOT_REGISTERED;
   137     }
   139     if (NS_SUCCEEDED(rv)) {
   140         // The standard return case:
   141         rv = aboutMod->NewChannel(uri, result);
   142         if (NS_SUCCEEDED(rv)) {
   143             // If this URI is safe for untrusted content, enforce that its
   144             // principal be based on the channel's originalURI by setting the
   145             // owner to null.
   146             // Note: this relies on aboutMod's newChannel implementation
   147             // having set the proper originalURI, which probably isn't ideal.
   148             if (IsSafeForUntrustedContent(aboutMod, uri)) {
   149                 (*result)->SetOwner(nullptr);
   150             }
   152             nsRefPtr<nsNestedAboutURI> aboutURI;
   153             nsresult rv2 = uri->QueryInterface(kNestedAboutURICID,
   154                                                getter_AddRefs(aboutURI));
   155             if (NS_SUCCEEDED(rv2) && aboutURI->GetBaseURI()) {
   156                 nsCOMPtr<nsIWritablePropertyBag2> writableBag =
   157                     do_QueryInterface(*result);
   158                 if (writableBag) {
   159                     writableBag->
   160                         SetPropertyAsInterface(NS_LITERAL_STRING("baseURI"),
   161                                                aboutURI->GetBaseURI());
   162                 }
   163             }
   164         }
   165         return rv;
   166     }
   168     // mumble...
   170     if (rv == NS_ERROR_FACTORY_NOT_REGISTERED) {
   171         // This looks like an about: we don't know about.  Convert
   172         // this to an invalid URI error.
   173         rv = NS_ERROR_MALFORMED_URI;
   174     }
   176     return rv;
   177 }
   179 NS_IMETHODIMP 
   180 nsAboutProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
   181 {
   182     // don't override anything.  
   183     *_retval = false;
   184     return NS_OK;
   185 }
   187 ////////////////////////////////////////////////////////////////////////////////
   188 // Safe about protocol handler impl
   190 NS_IMPL_ISUPPORTS(nsSafeAboutProtocolHandler, nsIProtocolHandler)
   192 // nsIProtocolHandler methods:
   194 NS_IMETHODIMP
   195 nsSafeAboutProtocolHandler::GetScheme(nsACString &result)
   196 {
   197     result.AssignLiteral("moz-safe-about");
   198     return NS_OK;
   199 }
   201 NS_IMETHODIMP
   202 nsSafeAboutProtocolHandler::GetDefaultPort(int32_t *result)
   203 {
   204     *result = -1;        // no port for moz-safe-about: URLs
   205     return NS_OK;
   206 }
   208 NS_IMETHODIMP
   209 nsSafeAboutProtocolHandler::GetProtocolFlags(uint32_t *result)
   210 {
   211     *result = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_ANYONE | URI_SAFE_TO_LOAD_IN_SECURE_CONTEXT;
   212     return NS_OK;
   213 }
   215 NS_IMETHODIMP
   216 nsSafeAboutProtocolHandler::NewURI(const nsACString &aSpec,
   217                                    const char *aCharset, // ignore charset info
   218                                    nsIURI *aBaseURI,
   219                                    nsIURI **result)
   220 {
   221     nsresult rv;
   223     nsCOMPtr<nsIURI> url = do_CreateInstance(kSimpleURICID, &rv);
   224     if (NS_FAILED(rv)) return rv;
   226     rv = url->SetSpec(aSpec);
   227     if (NS_FAILED(rv)) {
   228         return rv;
   229     }
   231     NS_TryToSetImmutable(url);
   233     *result = nullptr;
   234     url.swap(*result);
   235     return rv;
   236 }
   238 NS_IMETHODIMP
   239 nsSafeAboutProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
   240 {
   241     *result = nullptr;
   242     return NS_ERROR_NOT_AVAILABLE;
   243 }
   245 NS_IMETHODIMP 
   246 nsSafeAboutProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
   247 {
   248     // don't override anything.  
   249     *_retval = false;
   250     return NS_OK;
   251 }
   253 ////////////////////////////////////////////////////////////
   254 // nsNestedAboutURI implementation
   255 NS_INTERFACE_MAP_BEGIN(nsNestedAboutURI)
   256   if (aIID.Equals(kNestedAboutURICID))
   257       foundInterface = static_cast<nsIURI*>(this);
   258   else
   259 NS_INTERFACE_MAP_END_INHERITING(nsSimpleNestedURI)
   261 // nsISerializable
   262 NS_IMETHODIMP
   263 nsNestedAboutURI::Read(nsIObjectInputStream* aStream)
   264 {
   265     nsresult rv = nsSimpleNestedURI::Read(aStream);
   266     if (NS_FAILED(rv)) return rv;
   268     bool haveBase;
   269     rv = aStream->ReadBoolean(&haveBase);
   270     if (NS_FAILED(rv)) return rv;
   272     if (haveBase) {
   273         nsCOMPtr<nsISupports> supports;
   274         rv = aStream->ReadObject(true, getter_AddRefs(supports));
   275         if (NS_FAILED(rv)) return rv;
   277         mBaseURI = do_QueryInterface(supports, &rv);
   278         if (NS_FAILED(rv)) return rv;
   279     }
   281     return NS_OK;
   282 }
   284 NS_IMETHODIMP
   285 nsNestedAboutURI::Write(nsIObjectOutputStream* aStream)
   286 {
   287     nsresult rv = nsSimpleNestedURI::Write(aStream);
   288     if (NS_FAILED(rv)) return rv;
   290     rv = aStream->WriteBoolean(mBaseURI != nullptr);
   291     if (NS_FAILED(rv)) return rv;
   293     if (mBaseURI) {
   294         // A previous iteration of this code wrote out mBaseURI as nsISupports
   295         // and then read it in as nsIURI, which is non-kosher when mBaseURI
   296         // implements more than just a single line of interfaces and the
   297         // canonical nsISupports* isn't the one a static_cast<> of mBaseURI
   298         // would produce.  For backwards compatibility with existing
   299         // serializations we continue to write mBaseURI as nsISupports but
   300         // switch to reading it as nsISupports, with a post-read QI to get to
   301         // nsIURI.
   302         rv = aStream->WriteCompoundObject(mBaseURI, NS_GET_IID(nsISupports),
   303                                           true);
   304         if (NS_FAILED(rv)) return rv;
   305     }
   307     return NS_OK;
   308 }
   310 // nsSimpleURI
   311 /* virtual */ nsSimpleURI*
   312 nsNestedAboutURI::StartClone(nsSimpleURI::RefHandlingEnum aRefHandlingMode)
   313 {
   314     // Sadly, we can't make use of nsSimpleNestedURI::StartClone here.
   315     // However, this function is expected to exactly match that function,
   316     // aside from the "new ns***URI()" call.
   317     NS_ENSURE_TRUE(mInnerURI, nullptr);
   319     nsCOMPtr<nsIURI> innerClone;
   320     nsresult rv = aRefHandlingMode == eHonorRef ?
   321         mInnerURI->Clone(getter_AddRefs(innerClone)) :
   322         mInnerURI->CloneIgnoringRef(getter_AddRefs(innerClone));
   324     if (NS_FAILED(rv)) {
   325         return nullptr;
   326     }
   328     nsNestedAboutURI* url = new nsNestedAboutURI(innerClone, mBaseURI);
   329     url->SetMutable(false);
   331     return url;
   332 }
   334 // nsIClassInfo
   335 NS_IMETHODIMP
   336 nsNestedAboutURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
   337 {
   338     *aClassIDNoAlloc = kNestedAboutURICID;
   339     return NS_OK;
   340 }

mercurial