WebCore:
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Jan 2005 01:28:51 +0000 (01:28 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Jan 2005 01:28:51 +0000 (01:28 +0000)
        Reviewed by Darin.

<rdar://problem/3888931> frame naming allows malicious site to bring up a window when you click on a link in another

Added opener bridge method to help WebKit implement security check
for named frame visibility.

* khtml/khtml_part.h:
        * kwq/WebCoreBridge.h:
        * kwq/WebCoreBridge.mm:
        (-[WebCoreBridge opener]):

WebKit:

        Reviewed by Darin.

<rdar://problem/3888931> frame naming allows malicious site to bring up a window when you click on a link in another

        Implement a security check on name frame visbility. This is the
same rule as mozilla. You can only target frames by name if you
are in the same window, have the same domain as the frame or an
ancestor, or if it's a top level window have the same domain as
the opener.

        * WebView.subproj/WebFrame.m:
        (-[WebFrame _shouldAllowAccessFrom:]):
        (-[WebFrame _descendantFrameNamed:sourceFrame:]):
        (-[WebFrame findFrameNamed:]):
        * WebView.subproj/WebFramePrivate.h:
        * WebView.subproj/WebView.m:
        (-[WebView _findFrameInThisWindowNamed:sourceFrame:]):
        (-[WebView _findFrameNamed:sourceFrame:]):
        * WebView.subproj/WebViewPrivate.h:

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

WebCore/ChangeLog-2005-08-23
WebCore/khtml/ecma/kjs_window.cpp
WebCore/khtml/khtml_part.cpp
WebCore/khtml/khtml_part.h
WebCore/kwq/WebCoreBridge.h
WebCore/kwq/WebCoreBridge.mm
WebKit/ChangeLog
WebKit/WebView.subproj/WebFrame.m
WebKit/WebView.subproj/WebFramePrivate.h
WebKit/WebView.subproj/WebView.m
WebKit/WebView.subproj/WebViewPrivate.h

index b92c2a59c1730897288f4a4e51896be842dabfa3..150d47c80753bdf7365f0434fbf7c98405c1efab 100644 (file)
@@ -1,3 +1,17 @@
+2004-12-21  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+       <rdar://problem/3888931> frame naming allows malicious site to bring up a window when you click on a link in another
+        
+       Added opener bridge method to help WebKit implement security check
+       for named frame visibility.
+       
+       * khtml/khtml_part.h:
+        * kwq/WebCoreBridge.h:
+        * kwq/WebCoreBridge.mm:
+        (-[WebCoreBridge opener]):
+
 2005-01-03  Ken Kocienda  <kocienda@apple.com>
 
         Reviewed by John
index 6ea1ad908223f4e000bfbaf15281e58472253b0f..5583a342b5c3d5fd4aa06d56aee15f73e9d91e6c 100644 (file)
@@ -470,6 +470,12 @@ Value Window::get(ExecState *exec, const Identifier &p) const
       return Value(val);
   }
 
+  // Check for child frames by name before built-in properties to
+  // match behavior of other browsers.
+  KHTMLPart *childFrame = m_part->childFrameNamed(p.ustring().qstring());
+  if (childFrame) 
+    return retrieve(childFrame);
+
   const HashEntry* entry = Lookup::findEntry(&WindowTable, p);
   if (entry)
   {
index d346de6e2e18343f2319ac14f58e3f7ae248e3b5..67b64c4e2138dafe0151d4403cf5daaa3db1057f 100644 (file)
@@ -4330,6 +4330,15 @@ QPtrList<KParts::ReadOnlyPart> KHTMLPart::frames() const
   return res;
 }
 
+KHTMLPart *KHTMLPart::childFrameNamed(const QString &name) const
+{
+  FrameList::Iterator it = d->m_frames.find(name);
+  if (it != d->m_frames.end())
+    return static_cast<KHTMLPart *>(&*(*it).m_part);
+  return NULL;
+}
+
+
 #if !APPLE_CHANGES
 
 bool KHTMLPart::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
index beb6bff37ada6aa26d9f48200c9f70338a35dcc7..dcc56bbce01b1f536b14b1152bcd7ea7bad12ac0 100644 (file)
@@ -793,6 +793,8 @@ public:
 
   QPtrList<KParts::ReadOnlyPart> frames() const;
 
+  KHTMLPart *childFrameNamed(const QString &name) const;
+
   /**
    * Finds a frame by name. Returns 0L if frame can't be found.
    */
@@ -1295,7 +1297,13 @@ private:
 
   KJSProxy *jScript();
 
+#if APPLE_CHANGES
+ public:
+#endif
   KHTMLPart *opener();
+#if APPLE_CHANGES
+ private:
+#endif
   long cacheId() const;
   void setOpener(KHTMLPart *_opener);
   bool openedByJS();
index 8d01f719dceaa09c6de2529f3e54c04243b6dde9..aebfadc49dc8b38e0c5b071e0961aa7df020105f 100644 (file)
@@ -218,6 +218,7 @@ typedef enum {
 - (NSURL *)URL;
 - (NSString *)referrer;
 - (NSString *)domain;
+- (WebCoreBridge *)opener;
 
 - (void)installInFrame:(NSView *)view;
 - (void)removeFromFrame;
index 44fda8541a102868d1ae75a30d54029550f25f9f..df78c7f4984b55b5b366e0bf5d5f0355f214b5d0 100644 (file)
@@ -1274,6 +1274,16 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
     return nil;
 }
 
+- (WebCoreBridge *)opener
+{
+    KHTMLPart *openerPart = _part->opener();
+
+    if (openerPart)
+        return KWQ(openerPart)->bridge();
+
+    return nil;
+}
+
 + (NSString *)stringWithData:(NSData *)data textEncoding:(CFStringEncoding)textEncoding
 {
     if (textEncoding == kCFStringEncodingInvalidId || textEncoding == kCFStringEncodingISOLatin1) {
index b34ed63bbe76f0099ea625bcdb9932ce4d1b3272..abe64de7e37141dd32d977e8a2c0e8cf32ce6a3b 100644 (file)
@@ -1,3 +1,25 @@
+2004-12-21  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+       <rdar://problem/3888931> frame naming allows malicious site to bring up a window when you click on a link in another
+
+        Implement a security check on name frame visbility. This is the
+       same rule as mozilla. You can only target frames by name if you
+       are in the same window, have the same domain as the frame or an
+       ancestor, or if it's a top level window have the same domain as
+       the opener.
+       
+        * WebView.subproj/WebFrame.m:
+        (-[WebFrame _shouldAllowAccessFrom:]):
+        (-[WebFrame _descendantFrameNamed:sourceFrame:]):
+        (-[WebFrame findFrameNamed:]):
+        * WebView.subproj/WebFramePrivate.h:
+        * WebView.subproj/WebView.m:
+        (-[WebView _findFrameInThisWindowNamed:sourceFrame:]):
+        (-[WebView _findFrameNamed:sourceFrame:]):
+        * WebView.subproj/WebViewPrivate.h:
+
 === Safari-177 ===
 
 === Safari-176 ===
index 1034612be02a006a6d77209dcaec72891fdc5f7d..b18132afe46e42d2b523bb187050e079ce21b3d2 100644 (file)
@@ -484,9 +484,55 @@ NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
     return [_private->bridge isFrameSet];
 }
 
-- (WebFrame *)_descendantFrameNamed:(NSString *)name
+- (BOOL)_shouldAllowAccessFrom:(WebFrame *)source
 {
-    if ([[self name] isEqualToString: name]){
+    // if no source frame, allow access
+    if (source == nil) {
+        return YES;
+    }
+
+    //   - allow access if the two frames are in the same window
+    if ([self webView] == [source webView]) {
+        return YES;
+    }
+
+    //   - allow if the request is made from a local file.
+    NSString *sourceDomain = [[source _bridge] domain];
+    if ([sourceDomain length] == 0) {
+        return YES;
+    }
+
+    //   - allow access if this frame or one of its ancestors
+    //     has the same origin as source
+    WebFrame *ancestor = self;
+    while (ancestor != nil) {
+        NSString *ancestorDomain = [[ancestor _bridge] domain];
+        if (ancestorDomain != nil && [sourceDomain _web_isCaseInsensitiveEqualToString:ancestorDomain]) {
+            return YES;
+        }
+        ancestor = [ancestor parentFrame];
+    }
+
+    //   - allow access if this frame is a toplevel window and the source
+    //     can access its opener. Note that we only allow one level of
+    //     recursion here.
+    if ([self parentFrame] == nil) {
+        NSString *openerDomain = [[[self _bridge] opener] domain];
+        if (openerDomain != nil && [sourceDomain _web_isCaseInsensitiveEqualToString:openerDomain]) {
+            return YES;
+        }
+    }
+
+    // otherwise deny access
+    return NO;
+}
+
+
+- (WebFrame *)_descendantFrameNamed:(NSString *)name sourceFrame:(WebFrame *)source
+{
+    // for security reasons, we do not want to even make frames visible to frames that
+    // can't access them 
+    if ([[self name] isEqualToString: name] && [self _shouldAllowAccessFrom:source]) {
         return self;
     }
 
@@ -499,7 +545,7 @@ NSString *WebPageCacheDocumentViewKey = @"WebPageCacheDocumentViewKey";
 
     for (i = 0; i < [children count]; i++){
         frame = [children objectAtIndex: i];
-        frame = [frame _descendantFrameNamed:name];
+        frame = [frame _descendantFrameNamed:name sourceFrame:source];
         if (frame){
             return frame;
         }
@@ -2800,11 +2846,11 @@ static CFAbsoluteTime _timeOfLastCompletedLoad;
     }
 
     // Search from this frame down.
-    WebFrame *frame = [self _descendantFrameNamed:name];
+    WebFrame *frame = [self _descendantFrameNamed:name sourceFrame:self];
 
     if (!frame) {
         // Search in this WebView then in others.
-        frame = [[self webView] _findFrameNamed:name];
+        frame = [[self webView] _findFrameNamed:name sourceFrame:self];
     }
 
     return frame;
index f34f58907e60068675e5097e70bb310bd9f0fddf..570f1c0fc2a9f1f25218d17a4885f491c908b08f 100644 (file)
@@ -127,7 +127,7 @@ extern NSString *WebPageCacheDocumentViewKey;
 
 - (void)_setWebView:(WebView *)webView;
 - (void)_setName:(NSString *)name;
-- (WebFrame *)_descendantFrameNamed:(NSString *)name;
+- (WebFrame *)_descendantFrameNamed:(NSString *)name sourceFrame:(WebFrame *)source;
 - (void)_detachFromParent;
 - (void)_closeOldDataSources;
 - (void)_setDataSource:(WebDataSource *)d;
index fc7c13befa2c7230f050ee3647a0a4b95a24e834..cdfc7f0750dc7eefa1670d3378140d7b6d6353da 100644 (file)
@@ -431,15 +431,15 @@ NSString *_WebMainFrameURLKey =         @"mainFrameURL";
     [[self mainFrame] _setName:name];
 }
 
-- (WebFrame *)_findFrameInThisWindowNamed: (NSString *)name
+- (WebFrame *)_findFrameInThisWindowNamed:(NSString *)name sourceFrame:(WebFrame *)source
 {
-    return [[self mainFrame] _descendantFrameNamed:name];
+    return [[self mainFrame] _descendantFrameNamed:name sourceFrame:(WebFrame *)source];
 }
 
-- (WebFrame *)_findFrameNamed:(NSString *)name
+- (WebFrame *)_findFrameNamed:(NSString *)name sourceFrame:(WebFrame *)source
 {
     // Try this WebView first.
-    WebFrame *frame = [self _findFrameInThisWindowNamed:name];
+    WebFrame *frame = [self _findFrameInThisWindowNamed:name sourceFrame:source];
 
     if (frame != nil) {
         return frame;
@@ -450,7 +450,7 @@ NSString *_WebMainFrameURLKey =         @"mainFrameURL";
         NSEnumerator *enumerator = [WebViewSets webViewsInSetNamed:_private->setName];
         WebView *webView;
         while ((webView = [enumerator nextObject]) != nil && frame == nil) {
-           frame = [webView _findFrameInThisWindowNamed:name];
+           frame = [webView _findFrameInThisWindowNamed:name sourceFrame:source];
         }
     }
 
index 6c91c79e112c7abccda3de267409a160693003a7..0edee8bdb10010942aa271bf7923a4d325a0b6cf 100644 (file)
@@ -1,6 +1,6 @@
 /*     
-    WebViewPrivate.m
-    Copyright 2001, Apple, Inc. All rights reserved.
+    WebViewPrivate.h
+    Copyright 2001 Apple, Inc. All rights reserved.
 */
 
 #import <WebKit/WebView.h>
@@ -113,8 +113,8 @@ typedef enum {
 - (void)setDefersCallbacks:(BOOL)defers;
 
 - (void)_setTopLevelFrameName:(NSString *)name;
-- (WebFrame *)_findFrameInThisWindowNamed: (NSString *)name;
-- (WebFrame *)_findFrameNamed: (NSString *)name;
+- (WebFrame *)_findFrameInThisWindowNamed:(NSString *)name sourceFrame:(WebFrame *)source;
+- (WebFrame *)_findFrameNamed:(NSString *)name sourceFrame:(WebFrame *)source;
 
 - (WebView *)_openNewWindowWithRequest:(NSURLRequest *)request;