@@ -650,6 +650,40 @@ def fake_sendall(data):
650650 self .assertIn ('Error code: 400' , self .data )
651651 self .assertIn ('Message: URI must not start with //' , self .data )
652652
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+
653687 @mock .patch ('nova.objects.ConsoleAuthToken.validate' )
654688 def test_no_compute_rpcapi_with_invalid_token (self , mock_validate ):
655689 """Tests that we don't create a ComputeAPI object until we actually
0 commit comments