1 /*
   2  * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 6520665 6357133
  27  * @modules java.base/sun.net.www
  28  * @run main/othervm NTLMTest
  29  * @summary 6520665 & 6357133: NTLM authentication issues.
  30  */
  31 
  32 import java.net.*;
  33 import java.io.*;
  34 import sun.net.www.MessageHeader;
  35 
  36 public class NTLMTest
  37 {
  38     public static void main(String[] args) {
  39         Authenticator.setDefault(new NullAuthenticator());
  40 
  41         try {
  42             // Test with direct connection.
  43             ServerSocket serverSS = new ServerSocket(0);
  44             startServer(serverSS, false);
  45             runClient(Proxy.NO_PROXY, serverSS.getLocalPort());
  46 
  47             // Test with proxy.
  48             serverSS = new ServerSocket(0);
  49             startServer(serverSS, true /*proxy*/);
  50             SocketAddress proxyAddr = new InetSocketAddress("localhost", serverSS.getLocalPort());
  51             runClient(new Proxy(java.net.Proxy.Type.HTTP, proxyAddr), 8888);
  52 
  53         } catch (IOException e) {
  54             e.printStackTrace();
  55         }
  56     }
  57 
  58     static void runClient(Proxy proxy, int serverPort) {
  59         try {
  60             String urlStr = "http://localhost:" + serverPort + "/";
  61             URL url = new URL(urlStr);
  62             HttpURLConnection uc = (HttpURLConnection) url.openConnection(proxy);
  63             uc.getInputStream();
  64 
  65         } catch (ProtocolException e) {
  66             /* java.net.ProtocolException: Server redirected too many  times (20) */
  67             throw new RuntimeException("Failed: ProtocolException", e);
  68         } catch (IOException ioe) {
  69             /* IOException is OK. We are expecting "java.io.IOException: Server
  70              * returned HTTP response code: 401 for URL: ..."
  71              */
  72             //ioe.printStackTrace();
  73         } catch (NullPointerException npe) {
  74             throw new RuntimeException("Failed: NPE thrown ", npe);
  75         }
  76     }
  77 
  78     static String[] serverResp = new String[] {
  79                 "HTTP/1.1 401 Unauthorized\r\n" +
  80                 "Content-Length: 0\r\n" +
  81                 "WWW-Authenticate: NTLM\r\n\r\n",
  82 
  83                 "HTTP/1.1 401 Unauthorized\r\n" +
  84                 "Content-Length: 0\r\n" +
  85                 "WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==\r\n\r\n"};
  86 
  87     static String[] proxyResp = new String[] {
  88                 "HTTP/1.1 407 Proxy Authentication Required\r\n" +
  89                 "Content-Length: 0\r\n" +
  90                 "Proxy-Authenticate: NTLM\r\n\r\n",
  91 
  92                 "HTTP/1.1 407 Proxy Authentication Required\r\n" +
  93                 "Content-Length: 0\r\n" +
  94                 "Proxy-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==\r\n\r\n"};
  95 
  96     static void startServer(ServerSocket serverSS, boolean proxy) {
  97         final ServerSocket ss = serverSS;
  98         final boolean isProxy = proxy;
  99 
 100         Thread thread = new Thread(new Runnable() {
 101             public void run() {
 102                 boolean doing2ndStageNTLM = false;
 103                 while (true) {
 104                     try {
 105                         Socket s = ss.accept();
 106                         if (!doing2ndStageNTLM) {
 107                             handleConnection(s, isProxy ? proxyResp : serverResp, 0, 1);
 108                             doing2ndStageNTLM = true;
 109                         } else {
 110                             handleConnection(s, isProxy ? proxyResp : serverResp, 1, 2);
 111                             doing2ndStageNTLM = false;
 112                         }
 113                         connectionCount++;
 114                         //System.out.println("connectionCount = " + connectionCount);
 115 
 116                     } catch (IOException ioe) {
 117                         ioe.printStackTrace();
 118                     }
 119                 }
 120             } });
 121             thread.setDaemon(true);
 122             thread.start();
 123 
 124     }
 125 
 126     static int connectionCount = 0;
 127 
 128     static void handleConnection(Socket s, String[] resp, int start, int end) {
 129         try {
 130             OutputStream os = s.getOutputStream();
 131 
 132             for (int i=start; i<end; i++) {
 133                 MessageHeader header = new MessageHeader (s.getInputStream());
 134                 //System.out.println("Input :" + header);
 135                 //System.out.println("Output:" + resp[i]);
 136                 os.write(resp[i].getBytes("ASCII"));
 137             }
 138 
 139             s.close();
 140         } catch (IOException ioe) {
 141             ioe.printStackTrace();
 142         }
 143     }
 144 
 145     static class NullAuthenticator extends java.net.Authenticator
 146     {
 147         public int count = 0;
 148 
 149         protected PasswordAuthentication getPasswordAuthentication() {
 150             count++;
 151             System.out.println("NullAuthenticator.getPasswordAuthentication called " + count + " times");
 152 
 153             return null;
 154         }
 155 
 156         public int getCallCount() {
 157             return count;
 158         }
 159     }
 160 
 161 }