@@ -650,6 +650,40 @@ def fake_sendall(data):
650
650
self .assertIn ('Error code: 400' , self .data )
651
651
self .assertIn ('Message: URI must not start with //' , self .data )
652
652
653
+ def test_reject_open_redirect_3_slashes (self ):
654
+ # This will test the behavior when an attempt is made to cause an open
655
+ # redirect. It should be rejected.
656
+ mock_req = mock .MagicMock ()
657
+ mock_req .makefile ().readline .side_effect = [
658
+ b'GET ///example.com/%2F.. HTTP/1.1\r \n ' ,
659
+ b''
660
+ ]
661
+
662
+ # Collect the response data to verify at the end. The
663
+ # SimpleHTTPRequestHandler writes the response data by calling the
664
+ # request socket sendall() method.
665
+ self .data = b''
666
+
667
+ def fake_sendall (data ):
668
+ self .data += data
669
+
670
+ mock_req .sendall .side_effect = fake_sendall
671
+
672
+ client_addr = ('8.8.8.8' , 54321 )
673
+ mock_server = mock .MagicMock ()
674
+ # This specifies that the server will be able to handle requests other
675
+ # than only websockets.
676
+ mock_server .only_upgrade = False
677
+
678
+ # Constructing a handler will process the mock_req request passed in.
679
+ websocketproxy .NovaProxyRequestHandler (
680
+ mock_req , client_addr , mock_server )
681
+
682
+ # Verify no redirect happens and instead a 400 Bad Request is returned.
683
+ self .data = self .data .decode ()
684
+ self .assertIn ('Error code: 400' , self .data )
685
+ self .assertIn ('Message: URI must not start with //' , self .data )
686
+
653
687
@mock .patch ('nova.objects.ConsoleAuthToken.validate' )
654
688
def test_no_compute_rpcapi_with_invalid_token (self , mock_validate ):
655
689
"""Tests that we don't create a ComputeAPI object until we actually
0 commit comments