WebCore:
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 10 Mar 2005 01:00:28 +0000 (01:00 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 10 Mar 2005 01:00:28 +0000 (01:00 +0000)
        Reviewed by Darin.

<rdar://problem/4005575> Arbitrary file disclosure vulnerability due to ability to load local html from remote content

        * khtml/ecma/kjs_html.cpp:
        (KJS::HTMLDocument::putValue):
        * khtml/ecma/kjs_window.cpp:
        (Window::put):
        (WindowFunc::tryCall):
        (Location::put):
        (LocationFunc::tryCall):
        * khtml/khtml_part.cpp:
        (KHTMLPart::begin):
        (KHTMLPart::scheduleLocationChange):
        (KHTMLPart::slotRedirect):
        (KHTMLPart::processObjectRequest):
        * khtml/khtml_part.h:
        * khtml/khtmlpart_p.h:
        * kwq/KWQKHTMLPart.mm:
        (KWQKHTMLPart::openURLRequest):
        (KWQKHTMLPart::urlSelected):
        (KWQKHTMLPart::createPart):
        * kwq/KWQKHTMLPartBrowserExtension.mm:
        (KHTMLPartBrowserExtension::createNewWindow):
        * kwq/WebCoreBridge.h:
        * kwq/WebCoreBridge.mm:
        (hasCaseInsensitivePrefix):
        (-[WebCoreBridge didNotOpenURL:pageCache:]):
        (-[WebCoreBridge canLoadURL:fromReferrer:hideReferrer:]):

WebKit:

        Reviewed by Darin.

<rdar://problem/4005575> Arbitrary file disclosure vulnerability due to ability to load local html from remote content

* Plugins.subproj/WebBaseNetscapePluginView.m:
        (-[WebBaseNetscapePluginView requestWithURLCString:]):
        * Plugins.subproj/WebNetscapePluginEmbeddedView.m:
        (-[WebNetscapePluginEmbeddedView didStart]):
        * Plugins.subproj/WebNetscapePluginStream.m:
        (-[WebNetscapePluginStream initWithRequest:pluginPointer:notifyData:sendNotification:]):
        * WebCoreSupport.subproj/WebBridge.m:
        (-[WebBridge createWindowWithURL:frameName:]):
        (-[WebBridge startLoadingResource:withURL:customHeaders:]):
        (-[WebBridge startLoadingResource:withURL:customHeaders:postData:]):
        (-[WebBridge syncLoadResourceWithURL:customHeaders:postData:finalURL:responseHeaders:statusCode:]):
        (-[WebBridge loadURL:referrer:reload:userGesture:target:triggeringEvent:form:formValues:]):
        (-[WebBridge postWithURL:referrer:target:data:contentType:triggeringEvent:form:formValues:]):
        (-[WebBridge createChildFrameNamed:withURL:referrer:renderPart:allowsScrolling:marginWidth:marginHeight:]):
        (-[WebBridge viewForPluginWithURL:attributeNames:attributeValues:MIMEType:]):
        * WebView.subproj/WebFrame.m:
        (-[WebFrame _loadURL:referrer:intoChild:]):
        * WebView.subproj/WebFramePrivate.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8837 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
WebCore/ChangeLog-2005-08-23
WebCore/khtml/ecma/kjs_html.cpp
WebCore/khtml/ecma/kjs_window.cpp
WebCore/khtml/khtml_part.cpp
WebCore/khtml/khtml_part.h
WebCore/khtml/khtmlpart_p.h
WebCore/kwq/KWQKHTMLPart.mm
WebCore/kwq/KWQKHTMLPartBrowserExtension.mm
WebCore/kwq/WebCoreBridge.h
WebCore/kwq/WebCoreBridge.mm
WebKit/ChangeLog
WebKit/Plugins.subproj/WebBaseNetscapePluginView.m
WebKit/Plugins.subproj/WebNetscapePluginEmbeddedView.m
WebKit/Plugins.subproj/WebNetscapePluginStream.m
WebKit/WebCoreSupport.subproj/WebBridge.m
WebKit/WebView.subproj/WebFrame.m
WebKit/WebView.subproj/WebFramePrivate.h

index 34b61d057c484a7ce230b6eecabdc7f8371b0aa1..ff4e2052ea3a24b2850c59a00a0b0755dee931c4 100644 (file)
@@ -1,3 +1,35 @@
+2005-03-06  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+       <rdar://problem/4005575> Arbitrary file disclosure vulnerability due to ability to load local html from remote content
+        
+        * khtml/ecma/kjs_html.cpp:
+        (KJS::HTMLDocument::putValue):
+        * khtml/ecma/kjs_window.cpp:
+        (Window::put):
+        (WindowFunc::tryCall):
+        (Location::put):
+        (LocationFunc::tryCall):
+        * khtml/khtml_part.cpp:
+        (KHTMLPart::begin):
+        (KHTMLPart::scheduleLocationChange):
+        (KHTMLPart::slotRedirect):
+        (KHTMLPart::processObjectRequest):
+        * khtml/khtml_part.h:
+        * khtml/khtmlpart_p.h:
+        * kwq/KWQKHTMLPart.mm:
+        (KWQKHTMLPart::openURLRequest):
+        (KWQKHTMLPart::urlSelected):
+        (KWQKHTMLPart::createPart):
+        * kwq/KWQKHTMLPartBrowserExtension.mm:
+        (KHTMLPartBrowserExtension::createNewWindow):
+        * kwq/WebCoreBridge.h:
+        * kwq/WebCoreBridge.mm:
+        (hasCaseInsensitivePrefix):
+        (-[WebCoreBridge didNotOpenURL:pageCache:]):
+        (-[WebCoreBridge canLoadURL:fromReferrer:hideReferrer:]):
+
 2005-03-09  Richard Williamson   <rjw@apple.com>
 
        Fixed <rdar://problem/4032938> Safari: text layout for MS P Gothic font is corrupted
index da414a21f27558d0ec5a48b5bb93701a6e4af261..1866820ca8255bddf432e2dd7dc4f33c6857e59a 100644 (file)
@@ -395,9 +395,9 @@ void KJS::HTMLDocument::putValue(ExecState *exec, int token, const Value& value,
 #if APPLE_CHANGES
       // We want a new history item if this JS was called via a user gesture
       bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
-      part->scheduleLocationChange(str, !userGesture);
+      part->scheduleLocationChange(str, activePart->referrer(), !userGesture);
 #else
-      part->scheduleLocationChange(str, false/*don't lock history*/);
+      part->scheduleLocationChange(str, activePart->referrer(), false/*don't lock history*/);
 #endif
     }
     break;
index 9f84643b7ca1aab416e0f384554bd2540c134333..df1e9d885dc6c4addb97c98f97b091395b45cff4 100644 (file)
@@ -928,9 +928,9 @@ void Window::put(ExecState* exec, const Identifier &propertyName, const Value &v
           bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
 #if APPLE_CHANGES
           // We want a new history item if this JS was called via a user gesture
-          m_part->scheduleLocationChange(dstUrl, !userGesture, userGesture);
+          m_part->scheduleLocationChange(dstUrl, p->referrer(), !userGesture, userGesture);
 #else
-          m_part->scheduleLocationChange(dstUrl, false /*don't lock history*/, userGesture);
+          m_part->scheduleLocationChange(dstUrl, p->referrer(), false /*don't lock history*/, userGesture);
 #endif
         }
       }
@@ -1526,38 +1526,36 @@ Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
 
       // prepare arguments
       KURL url;
+      KHTMLPart* activePart = Window::retrieveActive(exec)->m_part;
       if (!str.isEmpty())
       {
-        KHTMLPart* p = Window::retrieveActive(exec)->m_part;
-        if ( p )
-          url = p->htmlDocument().completeURL(str).string();
+        if (activePart)
+          url = activePart->htmlDocument().completeURL(str).string();
       }
 
       KParts::URLArgs uargs;
       uargs.frameName = frameName;
       if ( uargs.frameName == "_top" )
       {
-         // FIXME: referrer?
           while ( part->parentPart() )
               part = part->parentPart();
 
           const Window* window = Window::retrieveWindow(part);
           if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
             bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
-            part->scheduleLocationChange(url.url(), false/*don't lock history*/, userGesture);
+            part->scheduleLocationChange(url.url(), activePart->referrer(), false/*don't lock history*/, userGesture);
           }
           return Window::retrieve(part);
       }
       if ( uargs.frameName == "_parent" )
       {
-         // FIXME: referrer?
           if ( part->parentPart() )
               part = part->parentPart();
 
           const Window* window = Window::retrieveWindow(part);
           if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
             bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
-            part->scheduleLocationChange(url.url(), false/*don't lock history*/, userGesture);
+            part->scheduleLocationChange(url.url(), activePart->referrer(), false/*don't lock history*/, userGesture);
           }
           return Window::retrieve(part);
       }
@@ -1565,6 +1563,7 @@ Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
 
       // request window (new or existing if framename is set)
       KParts::ReadOnlyPart *newPart = 0L;
+      uargs.metaData()["referrer"] = activePart->referrer();
       emit part->browserExtension()->createNewWindow("", uargs,winargs,newPart);
       if (newPart && newPart->inherits("KHTMLPart")) {
         KHTMLPart *khtmlpart = static_cast<KHTMLPart*>(newPart);
@@ -1593,17 +1592,17 @@ Value WindowFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
           const Window* window = Window::retrieveWindow(khtmlpart);
           if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
             bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
-            // FIXME: Need to pass referrer here.
-            khtmlpart->scheduleLocationChange(url.url(), false, userGesture);
+            khtmlpart->scheduleLocationChange(url.url(), activePart->referrer(), false, userGesture);
           } 
        }
 #else
         uargs.serviceType = QString::null;
         if (uargs.frameName == "_blank")
           uargs.frameName = QString::null;
-        if (!url.isEmpty())
-         // FIXME: need to pass referrer here
+        if (!url.isEmpty()) {
+          uargs.metaData()["referrer"] = activePart->referrer();
           emit khtmlpart->browserExtension()->openURLRequest(url,uargs);
+        }
 #endif
         return Window::retrieve(khtmlpart); // global object
       } else
@@ -2222,13 +2221,14 @@ void Location::put(ExecState *exec, const Identifier &p, const Value &v, int att
   }
 
   const Window* window = Window::retrieveWindow(m_part);
+  KHTMLPart* activePart = Window::retrieveActive(exec)->part();
   if (!url.url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
     bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
 #if APPLE_CHANGES
     // We want a new history item if this JS was called via a user gesture
-    m_part->scheduleLocationChange(url.url(), !userGesture, userGesture);
+    m_part->scheduleLocationChange(url.url(), activePart->referrer(), !userGesture, userGesture);
 #else
-    m_part->scheduleLocationChange(url.url(), false /*don't lock history*/, userGesture);
+    m_part->scheduleLocationChange(url.url(), activePart->referrer(), false /*don't lock history*/, userGesture);
 #endif
   }
 }
@@ -2270,7 +2270,7 @@ Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
         const Window* window = Window::retrieveWindow(part);
         if (!str.startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
           bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
-          part->scheduleLocationChange(p->htmlDocument().completeURL(str).string(), true /*lock history*/, userGesture);
+          part->scheduleLocationChange(p->htmlDocument().completeURL(str).string(), p->referrer(), true /*lock history*/, userGesture);
         }
       }
       break;
@@ -2278,9 +2278,10 @@ Value LocationFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
     case Location::Reload:
     {
       const Window* window = Window::retrieveWindow(part);
-     if (!part->url().url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
+      KHTMLPart* activePart = Window::retrieveActive(exec)->part();
+      if (!part->url().url().startsWith("javascript:", false) || (window && window->isSafeScript(exec))) {
         bool userGesture = static_cast<ScriptInterpreter *>(exec->dynamicInterpreter())->wasRunByUserGesture();
-        part->scheduleLocationChange(part->url().url(), true/*lock history*/, userGesture);
+        part->scheduleLocationChange(part->url().url(), activePart->referrer(), true/*lock history*/, userGesture);
       }
       break;
     }
index 9c601e4bf7a5a0543a5bbf9640b105c0ed7bfc44..029003154519c9f01e97ff50b7747c2558574981 100644 (file)
@@ -1075,6 +1075,7 @@ void KHTMLPart::clear()
   d->m_scheduledRedirection = noRedirectionScheduled;
   d->m_delayRedirect = 0;
   d->m_redirectURL = QString::null;
+  d->m_redirectReferrer = QString::null;
   d->m_redirectLockHistory = true;
   d->m_redirectUserGesture = false;
   d->m_bHTTPRefresh = false;
@@ -1506,7 +1507,7 @@ void KHTMLPart::begin( const KURL &url, int xOffset, int yOffset )
   ref.setUser(QSTRING_NULL);
   ref.setPass(QSTRING_NULL);
   ref.setRef(QSTRING_NULL);
-  d->m_referrer = ref.protocol().startsWith("http") ? ref.url() : "";
+  d->m_referrer = ref.url();
   m_url = url;
   KURL baseurl;
 
@@ -2003,6 +2004,7 @@ void KHTMLPart::scheduleRedirection( double delay, const QString &url, bool doLo
        d->m_scheduledRedirection = redirectionScheduled;
        d->m_delayRedirect = delay;
        d->m_redirectURL = url;
+       d->m_redirectReferrer = QString::null;
        d->m_redirectLockHistory = doLockHistory;
        d->m_redirectUserGesture = false;
 
@@ -2012,13 +2014,14 @@ void KHTMLPart::scheduleRedirection( double delay, const QString &url, bool doLo
     }
 }
 
-void KHTMLPart::scheduleLocationChange(const QString &url, bool lockHistory, bool userGesture)
+void KHTMLPart::scheduleLocationChange(const QString &url, const QString &referrer, bool lockHistory, bool userGesture)
 {
     // Handle a location change of a page with no document as a special case.
     // This may happen when a frame changes the location of another frame.
     d->m_scheduledRedirection = d->m_doc ? locationChangeScheduled : locationChangeScheduledDuringLoad;
     d->m_delayRedirect = 0;
     d->m_redirectURL = url;
+    d->m_redirectReferrer = referrer;
     d->m_redirectLockHistory = lockHistory;
     d->m_redirectUserGesture = userGesture;
     d->m_redirectionTimer.stop();
@@ -2054,6 +2057,7 @@ void KHTMLPart::scheduleHistoryNavigation( int steps )
     d->m_scheduledRedirection = historyNavigationScheduled;
     d->m_delayRedirect = 0;
     d->m_redirectURL = QString::null;
+    d->m_redirectReferrer = QString::null;
     d->m_scheduledHistoryNavigationSteps = steps;
     d->m_redirectionTimer.stop();
     if (d->m_bComplete)
@@ -2091,6 +2095,7 @@ void KHTMLPart::slotRedirect()
     }
   
   QString u = d->m_redirectURL;
+
   d->m_scheduledRedirection = noRedirectionScheduled;
   d->m_delayRedirect = 0;
   d->m_redirectURL = QString::null;
@@ -2111,6 +2116,10 @@ void KHTMLPart::slotRedirect()
     args.reload = true;
 
   args.setLockHistory( d->m_redirectLockHistory );
+  if (!d->m_redirectReferrer.isEmpty())
+    args.metaData()["referrer"] = d->m_redirectReferrer;
+  d->m_redirectReferrer = QString::null;
+
   urlSelected( u, 0, 0, "_self", args );
 }
 
@@ -3205,8 +3214,12 @@ bool KHTMLPart::processObjectRequest( khtml::ChildFrame *child, const KURL &_url
   if ( child->m_part )
   {
     KHTMLPart *part = static_cast<KHTMLPart *>(&*child->m_part);
-    if (part && part->inherits("KHTMLPart"))
-      part->openURL(url);
+    if (part && part->inherits("KHTMLPart")) {
+      KParts::URLArgs args;
+      if (!d->m_referrer.isEmpty())
+        args.metaData()["referrer"] = d->m_referrer;
+      KWQ(part)->openURLRequest(url, args);
+    }
   }
   else
   {
index f7dbadbd44564779592c1f3936967d291fcc0738..d2cabbf83c285b1fa47220eea65eb3b8b8e8e065 100644 (file)
@@ -397,7 +397,7 @@ public:
    * Schedules a location change.
    * This is used for JavaScript-triggered location changes.
    */
-  void scheduleLocationChange(const QString &url, bool lockHistory = true, bool userGesture = false);
+  void scheduleLocationChange(const QString &url, const QString &referrer, bool lockHistory = true, bool userGesture = false);
   bool isScheduledLocationChangePending() const;
 
   /**
index 66cbaece8a5fdbd251369739584624d04fa8d636..55e53eb45d2f7999c750e8ecd1a6d3965a3a5d5e 100644 (file)
@@ -308,6 +308,7 @@ public:
   RedirectionScheduled m_scheduledRedirection;
   double m_delayRedirect;
   QString m_redirectURL;
+  QString m_redirectReferrer;
   int m_scheduledHistoryNavigationSteps;
 
 #if !APPLE_CHANGES
index 56e743b39454dcfadc6ddfbb9dccb6d9e886454e..614fb588e855b214d91db0abd1ee7b858fb4e695 100644 (file)
@@ -328,8 +328,16 @@ void KWQKHTMLPart::openURLRequest(const KURL &url, const URLArgs &args)
 {
     KWQ_BLOCK_EXCEPTIONS;
 
+    NSString *referrer;
+    QString argsReferrer = args.metaData()["referrer"];
+    if (!argsReferrer.isEmpty()) {
+        referrer = argsReferrer.getNSString();
+    } else {
+        referrer = [_bridge referrer];
+    }
+
     [_bridge loadURL:url.getNSURL()
-            referrer:[_bridge referrer]
+            referrer:referrer
               reload:args.reload
          userGesture:true
               target:args.frameName.getNSString()
@@ -758,14 +766,24 @@ void KHTMLPart::frameDetached()
 void KWQKHTMLPart::urlSelected(const KURL &url, int button, int state, const URLArgs &args)
 {
     KWQ_BLOCK_EXCEPTIONS;
+
+    NSString *referrer;
+    QString argsReferrer = args.metaData()["referrer"];
+    if (!argsReferrer.isEmpty()) {
+        referrer = argsReferrer.getNSString();
+    } else {
+        referrer = [_bridge referrer];
+    }
+
     [_bridge loadURL:url.getNSURL()
-            referrer:[_bridge referrer]
+            referrer:referrer
               reload:args.reload
          userGesture:true
               target:args.frameName.getNSString()
      triggeringEvent:_currentEvent
                 form:nil
           formValues:nil];
+
     KWQ_UNBLOCK_EXCEPTIONS;
 }
 
@@ -801,6 +819,7 @@ ReadOnlyPart *KWQKHTMLPart::createPart(const ChildFrame &child, const KURL &url,
         }
         WebCoreBridge *childBridge = [_bridge createChildFrameNamed:child.m_name.getNSString()
                                                             withURL:url.getNSURL()
+                                                           referrer:child.m_args.metaData()["referrer"].getNSString()
                                                          renderPart:child.m_frame
                                                     allowsScrolling:allowsScrolling
                                                         marginWidth:marginWidth
index 39816913d3d986cb01a4d4ccebbc23c41bf75d5f..22d99374c0be17211cc2df85cce9eaf1f3b14618 100644 (file)
@@ -73,12 +73,21 @@ void KHTMLPartBrowserExtension::createNewWindow(const KURL &url,
     NSString *frameName = urlArgs.frameName.length() == 0 ? nil : urlArgs.frameName.getNSString();
     
     WebCoreBridge *bridge;
-    
+
+    NSString *referrer;
+    QString argsReferrer = urlArgs.metaData()["referrer"];
+    if (argsReferrer.length() > 0) {
+        referrer = argsReferrer.getNSString();
+    } else {
+        referrer = [_part->bridge() referrer];
+    }
+
+
     if (frameName != nil) {
        bridge = [_part->bridge() findFrameNamed:frameName];
        if (bridge != nil) {
            if (!url.isEmpty()) {
-               [bridge loadURL:url.getNSURL() referrer:[_part->bridge() referrer] reload:urlArgs.reload userGesture:true target:nil triggeringEvent:nil form:nil formValues:nil];
+               [bridge loadURL:url.getNSURL() referrer:referrer reload:urlArgs.reload userGesture:true target:nil triggeringEvent:nil form:nil formValues:nil];
            }
            [bridge focusWindow];
            if (partResult) {
index 3077e1663500c0cda371745bb463e1f5cbdf1e0c..693ee39569aeab9b3b5dc4707bfff8b6abfedab5 100644 (file)
@@ -206,6 +206,8 @@ typedef enum {
 
 - (void)didNotOpenURL:(NSURL *)URL pageCache:(NSDictionary *)pageCache;
 
+- (BOOL)canLoadURL:(NSURL *)URL fromReferrer:(NSString *)referrer hideReferrer:(BOOL *)hideReferrer;
+
 - (void)saveDocumentState;
 - (void)restoreDocumentState;
 
@@ -459,6 +461,7 @@ typedef enum {
 - (void)setIconURL:(NSURL *)URL withType:(NSString *)string;
 
 - (WebCoreBridge *)createChildFrameNamed:(NSString *)frameName withURL:(NSURL *)URL
+    referrer:(NSString *)referrer
     renderPart:(KHTMLRenderPart *)renderPart
     allowsScrolling:(BOOL)allowsScrolling marginWidth:(int)width marginHeight:(int)height;
 
index cd6c5dce5dcfe01a790aec1a7b1c80d425bd919d..b0000b96ace7bd83beb997bdb7f1ba1ad4fba812 100644 (file)
@@ -210,6 +210,12 @@ static BOOL partHasSelection(WebCoreBridge *bridge)
     return YES;
 }
 
+static BOOL hasCaseInsensitivePrefix(NSString *string, NSString *prefix)
+{
+    return [string rangeOfString:prefix options:(NSCaseInsensitiveSearch | NSAnchoredSearch)].location !=
+        NSNotFound;
+}
+
 @implementation WebCoreBridge
 
 static bool initializedObjectCacheSize = FALSE;
@@ -380,6 +386,15 @@ static bool initializedKJS = FALSE;
     [state invalidate];
 }
 
+- (BOOL)canLoadURL:(NSURL *)URL fromReferrer:(NSString *)referrer hideReferrer:(BOOL *)hideReferrer
+{
+    *hideReferrer = !hasCaseInsensitivePrefix(referrer,@"http:") && !hasCaseInsensitivePrefix(referrer, @"https:");
+    BOOL referrerIsFileURL = hasCaseInsensitivePrefix(referrer, @"file:");
+    BOOL URLIsFileURL = [[URL scheme] compare:@"file" options:(NSCaseInsensitiveSearch|NSLiteralSearch)] == NSOrderedSame;
+
+    return referrerIsFileURL || !URLIsFileURL;
+}
+
 - (void)saveDocumentState
 {
     DocumentImpl *doc = _part->xmlDocImpl();
index 86bb6d4b6c0c7578ffb5510464b145ca9c3a28a8..00a75aedc94415e700f7691e3a56cc255adfb4d2 100644 (file)
@@ -1,3 +1,28 @@
+2005-03-06  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+       <rdar://problem/4005575> Arbitrary file disclosure vulnerability due to ability to load local html from remote content
+        
+       * Plugins.subproj/WebBaseNetscapePluginView.m:
+        (-[WebBaseNetscapePluginView requestWithURLCString:]):
+        * Plugins.subproj/WebNetscapePluginEmbeddedView.m:
+        (-[WebNetscapePluginEmbeddedView didStart]):
+        * Plugins.subproj/WebNetscapePluginStream.m:
+        (-[WebNetscapePluginStream initWithRequest:pluginPointer:notifyData:sendNotification:]):
+        * WebCoreSupport.subproj/WebBridge.m:
+        (-[WebBridge createWindowWithURL:frameName:]):
+        (-[WebBridge startLoadingResource:withURL:customHeaders:]):
+        (-[WebBridge startLoadingResource:withURL:customHeaders:postData:]):
+        (-[WebBridge syncLoadResourceWithURL:customHeaders:postData:finalURL:responseHeaders:statusCode:]):
+        (-[WebBridge loadURL:referrer:reload:userGesture:target:triggeringEvent:form:formValues:]):
+        (-[WebBridge postWithURL:referrer:target:data:contentType:triggeringEvent:form:formValues:]):
+        (-[WebBridge createChildFrameNamed:withURL:referrer:renderPart:allowsScrolling:marginWidth:marginHeight:]):
+        (-[WebBridge viewForPluginWithURL:attributeNames:attributeValues:MIMEType:]):
+        * WebView.subproj/WebFrame.m:
+        (-[WebFrame _loadURL:referrer:intoChild:]):
+        * WebView.subproj/WebFramePrivate.h:
+
 2005-03-09  Richard Williamson   <rjw@apple.com>
        
        Fixed <rdar://problem/4032938> Safari: text layout for MS P Gothic font is corrupted
index 8dc64d374480dc51dd4613ee15939dba52bb50ea..ffca44681d84fe5af689a878dc96e56494633a09 100644 (file)
@@ -1353,7 +1353,7 @@ static OSStatus TSMEventHandler(EventHandlerCallRef inHandlerRef, EventRef inEve
         return nil;
     }
     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
-    [request setHTTPReferrer:[[[[self dataSource] request] URL] _web_originalDataAsString]];
+    [request setHTTPReferrer:[[[self webFrame] _bridge] referrer]];
     return request;
 }
 
index 1f67e08439f2b275825cdf2abf1c6a1b617196ea..b061a629253348da0a8db4ca907af38daa72593e 100644 (file)
@@ -6,8 +6,10 @@
 #import <WebKit/WebNetscapePluginEmbeddedView.h>
 
 #import <WebKit/WebBaseNetscapePluginViewPrivate.h>
+#import <WebKit/WebBridge.h>
 #import <WebKit/WebDataSource.h>
 #import <WebKit/WebFrame.h>
+#import <WebKit/WebFramePrivate.h>
 #import <WebKit/WebFrameView.h>
 #import <WebKit/WebNetscapePluginPackage.h>
 #import <WebKit/WebNSViewExtras.h>
@@ -57,7 +59,7 @@
     // Check for this and don't start a load in this case.
     if (URL != nil && ![URL _web_isEmpty]) {
         NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
-        [request setHTTPReferrer:[[[[self dataSource] request] URL] _web_originalDataAsString]];
+        [request setHTTPReferrer:[[[self webFrame] _bridge] referrer]];
         [self loadRequest:request inTarget:nil withNotifyData:nil sendNotification:NO];
     }
 }
index e23dd4f837d3cf9ccca0b1e12394333eac19fa06..1097385afa8059fb86aab59b061852b3714dd963 100644 (file)
@@ -6,6 +6,7 @@
 #import <WebKit/WebNetscapePluginStream.h>
 
 #import <WebKit/WebBaseResourceHandleDelegate.h>
+#import <WebKit/WebBridge.h>
 #import <WebKit/WebDataSourcePrivate.h>
 #import <WebKit/WebKitErrorsPrivate.h>
 #import <WebKit/WebKitLogging.h>
@@ -16,7 +17,7 @@
 #import <Foundation/NSError_NSURLExtras.h>
 #import <Foundation/NSURLConnection.h>
 #import <Foundation/NSURLResponsePrivate.h>
-#import <Foundation/NSURLRequest.h>
+#import <Foundation/NSURLRequestPrivate.h>
 
 @interface WebNetscapePluginConnectionDelegate : WebBaseResourceHandleDelegate
 {
        notifyData:(void *)theNotifyData 
  sendNotification:(BOOL)flag
 {   
+    WebBaseNetscapePluginView *view = (WebBaseNetscapePluginView *)thePluginPointer->ndata;
+
+    WebBridge *bridge = [[view webFrame] _bridge];
+    BOOL hideReferrer;
+    if (![bridge canLoadURL:[request URL] fromReferrer:[bridge referrer] hideReferrer:&hideReferrer])
+        return nil;
+
     if ([self initWithRequestURL:[theRequest URL]
                     pluginPointer:thePluginPointer
                        notifyData:theNotifyData
         return nil;
     }
         
-    request = [theRequest copy];
+    request = [theRequest mutableCopy];
+    if (hideReferrer) {
+        [(NSMutableURLRequest *)request setHTTPReferrer:nil];
+    }
 
-    WebBaseNetscapePluginView *view = (WebBaseNetscapePluginView *)instance->ndata;
     _loader = [[WebNetscapePluginConnectionDelegate alloc] initWithStream:self view:view]; 
     [_loader setDataSource:[view dataSource]];
     
index 63eee5cc70cc727b64ce0d2ca96f3026382dec71..b54375a552151e6a961bc304419477ae075f9a00 100644 (file)
@@ -422,10 +422,14 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
        return nil;
     }
 
+    BOOL hideReferrer;
+    if (![self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer])
+        return nil;
+
     return [WebSubresourceClient startLoadingResource:resourceLoader
                                               withURL:URL
-                                       customHeaders:customHeaders
-                                             referrer:[self referrer]
+                                        customHeaders:customHeaders
+                                             referrer:(hideReferrer ? nil : [self referrer])
                                         forDataSource:[self dataSource]];
 }
 
@@ -437,11 +441,15 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
        return nil;
     }
 
+    BOOL hideReferrer;
+    if (![self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer])
+        return nil;
+
     return [WebSubresourceClient startLoadingResource:resourceLoader
                                               withURL:URL
                                        customHeaders:customHeaders
                                             postData:postData
-                                             referrer:[self referrer]
+                                             referrer:(hideReferrer ? nil : [self referrer])
                                         forDataSource:[self dataSource]];
 }
 
@@ -464,6 +472,10 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
 
 - (NSData *)syncLoadResourceWithURL:(NSURL *)URL customHeaders:(NSDictionary *)requestHeaders postData:(NSArray *)postData finalURL:(NSURL **)finalURL responseHeaders:(NSDictionary **)responseHeaderDict statusCode:(int *)statusCode
 {
+    BOOL hideReferrer;
+    if (![self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer])
+        return nil;
+
     NSMutableURLRequest *newRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
 
     if (postData) {
@@ -479,7 +491,8 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
     
     // Never use cached data for these requests (xmlhttprequests).
     [newRequest setCachePolicy:[[[self dataSource] request] cachePolicy]];
-    [newRequest setHTTPReferrer:[self referrer]];
+    if (!hideReferrer)
+        [newRequest setHTTPReferrer:[self referrer]];
     
     WebView *webView = [_frame webView];
     [newRequest setMainDocumentURL:[[[[webView mainFrame] dataSource] request] URL]];
@@ -616,6 +629,10 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
 
 - (void)loadURL:(NSURL *)URL referrer:(NSString *)referrer reload:(BOOL)reload userGesture:(BOOL)forUser target:(NSString *)target triggeringEvent:(NSEvent *)event form:(DOMElement *)form formValues:(NSDictionary *)values
 {
+    BOOL hideReferrer;
+    if (![self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer])
+        return;
+
     if ([target length] == 0) {
        target = nil;
     }
@@ -633,7 +650,7 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
         loadType = WebFrameLoadTypeInternal;
     else
         loadType = WebFrameLoadTypeStandard;
-    [_frame _loadURL:URL referrer:referrer loadType:loadType target:target triggeringEvent:event form:form formValues:values];
+    [_frame _loadURL:URL referrer:(hideReferrer ? nil : referrer) loadType:loadType target:target triggeringEvent:event form:form formValues:values];
 
     if (targetFrame != nil && _frame != targetFrame) {
        [[targetFrame _bridge] focusWindow];
@@ -642,6 +659,10 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
 
 - (void)postWithURL:(NSURL *)URL referrer:(NSString *)referrer target:(NSString *)target data:(NSArray *)postData contentType:(NSString *)contentType triggeringEvent:(NSEvent *)event form:(DOMElement *)form formValues:(NSDictionary *)values
 {
+    BOOL hideReferrer;
+    if (![self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer])
+        return;
+
     if ([target length] == 0) {
        target = nil;
     }
@@ -651,7 +672,7 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
         return;
     }
 
-    [_frame _postWithURL:URL referrer:referrer target:target data:postData contentType:contentType triggeringEvent:event form:form formValues:values];
+    [_frame _postWithURL:URL referrer:(hideReferrer ? nil : referrer) target:target data:postData contentType:contentType triggeringEvent:event form:form formValues:values];
 
     if (targetFrame != nil && _frame != targetFrame) {
        [[targetFrame _bridge] focusWindow];
@@ -663,10 +684,18 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
     return [_frame _generateFrameName];
 }
 
-- (WebCoreBridge *)createChildFrameNamed:(NSString *)frameName withURL:(NSURL *)URL
-    renderPart:(KHTMLRenderPart *)childRenderPart
-    allowsScrolling:(BOOL)allowsScrolling marginWidth:(int)width marginHeight:(int)height
+- (WebCoreBridge *)createChildFrameNamed:(NSString *)frameName 
+                                 withURL:(NSURL *)URL
+                                referrer:(NSString *)referrer
+                              renderPart:(KHTMLRenderPart *)childRenderPart
+                         allowsScrolling:(BOOL)allowsScrolling 
+                             marginWidth:(int)width
+                            marginHeight:(int)height
 {
+    BOOL hideReferrer;
+    if (![self canLoadURL:URL fromReferrer:referrer hideReferrer:&hideReferrer])
+        return nil;
+
     ASSERT(_frame != nil);
     WebFrame *newFrame = [[_frame webView] _createFrameNamed:frameName inParent:_frame allowsScrolling:allowsScrolling];
     if (newFrame == nil) {
@@ -678,7 +707,7 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
     [[newFrame frameView] _setMarginWidth:width];
     [[newFrame frameView] _setMarginHeight:height];
 
-    [_frame _loadURL:URL intoChild:newFrame];
+    [_frame _loadURL:URL referrer:(hideReferrer ? nil : referrer) intoChild:newFrame];
 
     return [newFrame _bridge];
 }
@@ -861,6 +890,10 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
                  attributeValues:(NSArray *)attributeValues
                         MIMEType:(NSString *)MIMEType
 {
+    BOOL hideReferrer;
+    if (![self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer])
+        return nil;
+
     ASSERT([attributeNames count] == [attributeValues count]);
 
     WebBasePluginPackage *pluginPackage = nil;
index 06bc03bbf90242bcdcd2e48fa14a231a35a3d82e..30b8e8815c6ca4c1851079901eeee281c3c26ae5 100644 (file)
@@ -1931,7 +1931,7 @@ static CFAbsoluteTime _timeOfLastCompletedLoad;
     [formState release];
 }
 
-- (void)_loadURL:(NSURL *)URL intoChild:(WebFrame *)childFrame
+- (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer intoChild:(WebFrame *)childFrame
 {
     WebHistoryItem *parentItem = [_private currentItem];
     NSArray *childItems = [parentItem children];
@@ -1975,8 +1975,7 @@ static CFAbsoluteTime _timeOfLastCompletedLoad;
     if (archive) {
         [childFrame loadArchive:archive];
     } else {
-        // FIXME: is this the right referrer?
-        [childFrame _loadURL:URL referrer:[[self _bridge] referrer] loadType:childLoadType target:nil triggeringEvent:nil form:nil formValues:nil];
+        [childFrame _loadURL:URL referrer:referrer loadType:childLoadType target:nil triggeringEvent:nil form:nil formValues:nil];
     }
 }
 
index 570f1c0fc2a9f1f25218d17a4885f491c908b08f..701ba3cfb06f9ab679dbe36566b5dff46b09d9ce 100644 (file)
@@ -152,7 +152,7 @@ extern NSString *WebPageCacheDocumentViewKey;
 
 - (void)_goToItem:(WebHistoryItem *)item withLoadType:(WebFrameLoadType)type;
 - (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer loadType:(WebFrameLoadType)loadType target:(NSString *)target triggeringEvent:(NSEvent *)event form:(DOMElement *)form formValues:(NSDictionary *)values;
-- (void)_loadURL:(NSURL *)URL intoChild:(WebFrame *)childFrame;
+- (void)_loadURL:(NSURL *)URL referrer:(NSString *)referrer intoChild:(WebFrame *)childFrame;
 - (void)_postWithURL:(NSURL *)URL referrer:(NSString *)referrer target:(NSString *)target data:(NSArray *)postData contentType:(NSString *)contentType triggeringEvent:(NSEvent *)event form:(DOMElement *)form formValues:(NSDictionary *)values;
 
 - (void)_loadRequest:(NSURLRequest *)request inFrameNamed:(NSString *)frameName;