NTLMAuthWithSM.java revision 12816:1de2065763c1
1/*
2 * Copyright (c) 2015, 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
24import com.sun.net.httpserver.HttpExchange;
25import com.sun.net.httpserver.HttpHandler;
26import com.sun.net.httpserver.HttpServer;
27import java.io.BufferedReader;
28import java.io.InputStreamReader;
29import java.io.IOException;
30import java.io.InputStream;
31import java.net.Authenticator;
32import java.net.InetSocketAddress;
33import java.net.PasswordAuthentication;
34import java.net.URL;
35import java.net.URLConnection;
36import java.util.List;
37import sun.net.www.protocol.http.ntlm.NTLMAuthenticationCallback;
38
39/*
40 * @test
41 * @bug 8137174
42 * @summary Checks if NTLM auth works fine if security manager set
43 * @run main/othervm/java.security.policy=NTLMAuthWithSM.policy NTLMAuthWithSM
44 */
45public class NTLMAuthWithSM {
46
47    public static void main(String[] args) throws Exception {
48        // security manager is required
49        if (System.getSecurityManager() == null) {
50            throw new RuntimeException("Security manager not specified");
51        }
52
53        if (System.getProperty("os.name").startsWith("Windows")) {
54            // disable transparent NTLM authentication on Windows
55            NTLMAuthenticationCallback.setNTLMAuthenticationCallback(
56                    new NTLMAuthenticationCallbackImpl());
57        }
58
59        try (LocalHttpServer server = LocalHttpServer.startServer()) {
60            // set authenticator
61            Authenticator.setDefault(new AuthenticatorImpl());
62
63            String url = String.format("http://localhost:%d/test/",
64                    server.getPort());
65
66            // load a document which is protected with NTML authentication
67            System.out.println("load() called: " + url);
68            URLConnection conn = new URL(url).openConnection();
69            try (BufferedReader reader = new BufferedReader(
70                    new InputStreamReader(conn.getInputStream()))) {
71
72                String line = reader.readLine();
73                if (line == null) {
74                    throw new IOException("Couldn't read a response");
75                }
76                do {
77                    System.out.println(line);
78                } while ((line = reader.readLine()) != null);
79            }
80        }
81
82        System.out.println("Test passed");
83    }
84
85    private static class AuthenticatorImpl extends Authenticator {
86
87        @Override
88        public PasswordAuthentication getPasswordAuthentication() {
89            System.out.println("getPasswordAuthentication() called, scheme: "
90                    + getRequestingScheme());
91            if (getRequestingScheme().equalsIgnoreCase("ntlm")) {
92                return new PasswordAuthentication("test", "test".toCharArray());
93            }
94            return null;
95        }
96    }
97
98    // local http server which pretends to support NTLM auth
99    static class LocalHttpServer implements HttpHandler, AutoCloseable {
100
101        private final HttpServer server;
102
103        private LocalHttpServer(HttpServer server) {
104            this.server = server;
105        }
106
107        static LocalHttpServer startServer() throws IOException {
108            HttpServer httpServer = HttpServer.create(
109                    new InetSocketAddress(0), 0);
110            LocalHttpServer localHttpServer = new LocalHttpServer(httpServer);
111            localHttpServer.start();
112
113            return localHttpServer;
114        }
115
116        void start() {
117            server.createContext("/test", this);
118            server.start();
119            System.out.println("HttpServer: started on port " + getPort());
120        }
121
122        void stop() {
123            server.stop(0);
124            System.out.println("HttpServer: stopped");
125        }
126
127        int getPort() {
128            return server.getAddress().getPort();
129        }
130
131        @Override
132        public void handle(HttpExchange t) throws IOException {
133            System.out.println("HttpServer: handle connection");
134
135            // read a request
136            try (InputStream is = t.getRequestBody()) {
137                while (is.read() > 0);
138            }
139
140            try {
141                List<String> headers = t.getRequestHeaders()
142                        .get("Authorization");
143                if (headers != null && !headers.isEmpty()
144                        && headers.get(0).trim().contains("NTLM")) {
145                    byte[] output = "hello".getBytes();
146                    t.sendResponseHeaders(200, output.length);
147                    t.getResponseBody().write(output);
148                    System.out.println("HttpServer: return 200");
149                } else {
150                    t.getResponseHeaders().set("WWW-Authenticate", "NTLM");
151                    byte[] output = "forbidden".getBytes();
152                    t.sendResponseHeaders(401, output.length);
153                    t.getResponseBody().write(output);
154                    System.out.println("HttpServer: return 401");
155                }
156            } catch (IOException e) {
157                System.out.println("HttpServer: exception: " + e);
158                System.out.println("HttpServer: return 500");
159                t.sendResponseHeaders(500, 0);
160            } finally {
161                t.close();
162            }
163        }
164
165        @Override
166        public void close() {
167            stop();
168        }
169    }
170
171    private static class NTLMAuthenticationCallbackImpl
172            extends NTLMAuthenticationCallback {
173
174        // don't trust any site, so that no transparent NTLM auth happens
175        @Override
176        public boolean isTrustedSite(URL url) {
177            System.out.println(
178                    "NTLMAuthenticationCallbackImpl.isTrustedSite() called: "
179                        + "return false");
180            return false;
181        }
182    }
183}
184