changeset 9908:09f903e77fa4

8225425: java.lang.UnsatisfiedLinkError: net.dll: Can't find dependent libraries Reviewed-by: dfuchs, alanb, erikj
author chegar
date Wed, 05 Feb 2020 04:51:10 +0000
parents 3a12e48a17c7
children 44ad311d28af
files make/java/net/Makefile src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c test/lib/testlibrary/jdk/testlibrary/net/URIBuilder.java test/sun/net/www/protocol/http/TestTransparentNTLM.java
diffstat 5 files changed, 356 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/make/java/net/Makefile	Wed Feb 05 04:41:50 2020 +0000
+++ b/make/java/net/Makefile	Wed Feb 05 04:51:10 2020 +0000
@@ -103,7 +103,7 @@
 else
 ifeq ($(PLATFORM), windows)
   OTHER_LDLIBS = ws2_32.lib $(JVMLIB) \
-                 secur32.lib iphlpapi.lib delayimp.lib urlmon.lib \
+                 secur32.lib iphlpapi.lib delayimp.lib \
                  /DELAYLOAD:secur32.dll /DELAYLOAD:iphlpapi.dll
 else
   OTHER_LDLIBS = $(LIBSOCKET) $(LIBNSL) $(LIBDL) $(JVMLIB)
--- a/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java	Wed Feb 05 04:41:50 2020 +0000
+++ b/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java	Wed Feb 05 04:51:10 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -194,7 +194,17 @@
         }
     }
 
-    static native boolean isTrustedSite(String url);
+    private static final boolean isTrustedSiteAvailable = isTrustedSiteAvailable();
+
+    private static native boolean isTrustedSiteAvailable();
+
+    private static boolean isTrustedSite(String url) {
+        if (isTrustedSiteAvailable)
+            return isTrustedSite0(url);
+        return false;
+    }
+
+    private static native boolean isTrustedSite0(String url);
 
     /**
      * Not supported. Must use the setHeaders() method
--- a/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c	Wed Feb 05 04:41:50 2020 +0000
+++ b/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c	Wed Feb 05 04:51:10 2020 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,11 +26,34 @@
 #include <jni.h>
 #include <windows.h>
 #include "jni_util.h"
+#include "jdk_util.h"
 #include <urlmon.h>
 
-JNIEXPORT jboolean JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthentication_isTrustedSite(JNIEnv *env, jclass clazz, jstring url )
+typedef HRESULT (WINAPI *CoInternetCreateSecurityManagerType)
+        (IServiceProvider*,IInternetSecurityManager**,DWORD);
+
+static CoInternetCreateSecurityManagerType fn_CoInternetCreateSecurityManager;
+
+JNIEXPORT jboolean JNICALL
+Java_sun_net_www_protocol_http_ntlm_NTLMAuthentication_isTrustedSiteAvailable
+  (JNIEnv *env, jclass clazz)
 {
+    HMODULE libUrlmon = JDK_LoadSystemLibrary("urlmon.dll");
+    if (libUrlmon != NULL) {
+        fn_CoInternetCreateSecurityManager = (CoInternetCreateSecurityManagerType)
+                GetProcAddress(libUrlmon, "CoInternetCreateSecurityManager");
+        if (fn_CoInternetCreateSecurityManager != NULL) {
+            return JNI_TRUE;
+        }
+    }
+    return JNI_FALSE;
+}
 
+
+JNIEXPORT jboolean JNICALL
+Java_sun_net_www_protocol_http_ntlm_NTLMAuthentication_isTrustedSite0
+  (JNIEnv *env, jclass clazz, jstring url)
+{
     HRESULT hr;
     DWORD dwZone;
     DWORD  pPolicy = 0;
@@ -38,8 +61,11 @@
     jboolean ret;
     LPCWSTR bstrURL;
 
+    if (fn_CoInternetCreateSecurityManager == NULL)
+        return JNI_FALSE;
+
     // Create IInternetSecurityManager
-    hr = CoInternetCreateSecurityManager(NULL, &spSecurityManager, (DWORD)0);
+    hr = fn_CoInternetCreateSecurityManager(NULL, &spSecurityManager, (DWORD)0);
     if (FAILED(hr)) {
         return JNI_FALSE;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/testlibrary/jdk/testlibrary/net/URIBuilder.java	Wed Feb 05 04:51:10 2020 +0000
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Google and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.testlibrary.net;
+
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+public class URIBuilder {
+
+    public static URIBuilder newBuilder() {
+        return new URIBuilder();
+    }
+
+    private String scheme;
+    private String userInfo;
+    private String host;
+    private int port;
+    private String path;
+    private String query;
+    private String fragment;
+
+    private URIBuilder() {}
+
+    public URIBuilder scheme(String scheme) {
+        this.scheme = scheme;
+        return this;
+    }
+
+    public URIBuilder userInfo(String userInfo) {
+        this.userInfo = userInfo;
+        return this;
+    }
+
+    public URIBuilder host(String host) {
+        this.host = host;
+        return this;
+    }
+
+    public URIBuilder loopback() {
+        return host(InetAddress.getLoopbackAddress().getHostAddress());
+    }
+
+    public URIBuilder port(int port) {
+        this.port = port;
+        return this;
+    }
+
+    public URIBuilder path(String path) {
+        this.path = path;
+        return this;
+    }
+
+    public URIBuilder query(String query) {
+        this.query = query;
+        return this;
+    }
+
+    public URIBuilder fragment(String fragment) {
+        this.fragment = fragment;
+        return this;
+    }
+
+    public URI build() throws URISyntaxException {
+        return new URI(scheme, userInfo, host, port, path, query, fragment);
+    }
+
+    public URI buildUnchecked() {
+        try {
+            return build();
+        } catch (URISyntaxException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    public URL toURL() throws URISyntaxException, MalformedURLException {
+        return build().toURL();
+    }
+
+    public URL toURLUnchecked() {
+        try {
+            return toURL();
+        } catch (URISyntaxException | MalformedURLException e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/net/www/protocol/http/TestTransparentNTLM.java	Wed Feb 05 04:51:10 2020 +0000
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8225425
+ * @summary Verifies that transparent NTLM (on Windows) is not used by default,
+ *          and is used only when the relevant property is set.
+ * @requires os.family == "windows"
+ * @library ../../../../../lib/testlibrary
+ * @run testng/othervm
+ *      -Dtest.auth.succeed=false
+ *      TestTransparentNTLM
+ * @run testng/othervm
+ *      -Djdk.http.ntlm.transparentAuth=allHosts
+ *      -Dtest.auth.succeed=true
+ *      TestTransparentNTLM
+ * @run testng/othervm
+ *      -Djdk.http.ntlm.transparentAuth=blahblah
+ *      -Dtest.auth.succeed=false
+ *      TestTransparentNTLM
+ * @run testng/othervm
+ *      -Djdk.http.ntlm.transparentAuth=trustedHosts
+ *      -Dtest.auth.succeed=false
+ *      TestTransparentNTLM
+ */
+
+// Run with `trustedHosts` to exercise the native code, nothing more.
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import jdk.testlibrary.net.URIBuilder;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import org.testng.SkipException;
+import static java.lang.System.out;
+import static java.net.Proxy.NO_PROXY;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+public class TestTransparentNTLM {
+
+    boolean succeed;  // true if authentication is expected to succeed
+    Server server;
+    URL url;
+
+    @Test
+    public void testNTLM() throws IOException {
+        out.println("connecting to url: " + url);
+        HttpURLConnection uc = (HttpURLConnection)url.openConnection(NO_PROXY);
+        int respCode = uc.getResponseCode();
+        out.println("received: " + respCode);
+
+        if (succeed) {
+            assertEquals(respCode, HttpURLConnection.HTTP_OK);
+            InputStream is = uc.getInputStream();
+            BufferedReader r = new BufferedReader(new InputStreamReader(is, UTF_8));
+            String body = r.readLine();
+            out.print("received body: ");
+            do {
+                out.print(body);
+                body = r.readLine();
+            } while (body != null);
+        } else {
+            assertEquals(respCode, HttpURLConnection.HTTP_UNAUTHORIZED);
+        }
+    }
+
+    static class Server extends Thread implements  Closeable {
+
+        static final InetAddress LOOPBACK = InetAddress.getLoopbackAddress();
+        final ServerSocket serverSocket;
+        final boolean expectAuthToSucceed;
+
+        Server(boolean expectAuthToSucceed) throws IOException {
+            super("TestTransparentNTLM-Server");
+            serverSocket = new ServerSocket();
+            serverSocket.bind(new InetSocketAddress(LOOPBACK, 0));
+            this.expectAuthToSucceed = expectAuthToSucceed;
+        }
+
+        int port() {
+            return serverSocket.getLocalPort();
+        }
+
+        static final String AUTH_REQUIRED =
+                "HTTP/1.1 401 Unauthorized\r\n" +
+                "Content-Length: 0\r\n" +
+                "Connection: close\r\n" +
+                "WWW-Authenticate: NTLM\r\n\r\n";
+
+        static final String AUTH_STAGE_TWO =
+                "HTTP/1.1 401 Unauthorized\r\n" +
+                "Content-Length: 0\r\n" +
+                "WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==\r\n\r\n";
+
+        static final String AUTH_SUCCESSFUL =
+                "HTTP/1.1 200 OK\r\n" +
+                "Content-Length: 11\r\n\r\n" +
+                "Hello world";
+
+        @Override
+        public void run() {
+            try {
+                try (Socket s = serverSocket.accept()) {
+                    out.println("Server accepted connection - 1");
+                    readRequestHeaders(s.getInputStream());
+                    s.getOutputStream().write(AUTH_REQUIRED.getBytes(UTF_8));
+                }
+
+                if (expectAuthToSucceed) {
+                    // await the second follow up connection
+                    try (Socket s = serverSocket.accept()) {
+                        out.println("Server accepted connection - 2");
+                        readRequestHeaders(s.getInputStream());
+                        s.getOutputStream().write(AUTH_STAGE_TWO.getBytes(UTF_8));
+                        readRequestHeaders(s.getInputStream());
+                        s.getOutputStream().write(AUTH_SUCCESSFUL.getBytes(UTF_8));
+                    }
+                }
+            } catch (IOException e) {
+                fail("Unexpected exception", e);
+            }
+        }
+
+        @Override
+        public void close() throws IOException {
+            serverSocket.close();
+        }
+
+        static final byte[] REQUEST_END = new byte[] {'\r', '\n', '\r', '\n'};
+
+        // Read until the end of the HTTP request headers
+        static void readRequestHeaders(InputStream is) throws IOException {
+            int requestEndCount = 0, r;
+            while ((r = is.read()) != -1) {
+                if (r == REQUEST_END[requestEndCount]) {
+                    requestEndCount++;
+                    if (requestEndCount == 4) {
+                        break;
+                    }
+                } else {
+                    requestEndCount = 0;
+                }
+            }
+        }
+    }
+
+    @BeforeTest
+    public void setup() throws Exception {
+        succeed = System.getProperty("test.auth.succeed").equals("true");
+        if (succeed)
+            out.println("Expect client to succeed, with 200 Ok");
+        else
+            out.println("Expect client to fail, with 401 Unauthorized");
+
+        server = new Server(succeed);
+        server.start();
+        url = URIBuilder.newBuilder()
+                .scheme("http")
+                .loopback()
+                .port(server.port())
+                .path("/xxyyzz")
+                .toURL();
+    }
+
+    @AfterTest
+    public void teardown() throws Exception {
+        server.close();
+        server.join();
+    }
+}