From 23a5b46dae8231ebe83711345531d0eff38bd556 Mon Sep 17 00:00:00 2001 From: chegar Date: Mon, 19 Aug 2019 14:28:43 +0100 Subject: [PATCH] 8225425: java.lang.UnsatisfiedLinkError: net.dll: Can't find dependent libraries Reviewed-by: dfuchs, alanb, erikj --- make/lib/NetworkingLibraries.gmk | 2 +- .../http/ntlm/NTLMAuthentication.java | 14 +- .../protocol/http/ntlm/NTLMAuthentication.c | 32 ++- .../jdk/testlibrary/net/URIBuilder.java | 111 ++++++++++ .../protocol/http/TestTransparentNTLM.java | 203 ++++++++++++++++++ 5 files changed, 356 insertions(+), 6 deletions(-) create mode 100644 test/lib/testlibrary/jdk/testlibrary/net/URIBuilder.java create mode 100644 test/sun/net/www/protocol/http/TestTransparentNTLM.java diff --git a/make/lib/NetworkingLibraries.gmk b/make/lib/NetworkingLibraries.gmk index 47006d0b8..347c32376 100644 --- a/make/lib/NetworkingLibraries.gmk +++ b/make/lib/NetworkingLibraries.gmk @@ -75,7 +75,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBNET, \ LDFLAGS_SUFFIX_linux := $(LIBDL) -ljvm -lpthread -ljava, \ LDFLAGS_SUFFIX_aix := $(LIBDL) -ljvm -ljava,\ LDFLAGS_SUFFIX_windows := ws2_32.lib jvm.lib secur32.lib iphlpapi.lib \ - delayimp.lib urlmon.lib $(WIN_JAVA_LIB) advapi32.lib \ + delayimp.lib $(WIN_JAVA_LIB) advapi32.lib \ -DELAYLOAD:secur32.dll -DELAYLOAD:iphlpapi.dll, \ VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/windows/resource/version.rc, \ RC_FLAGS := $(RC_FLAGS) \ diff --git a/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index 1b2c874e7..535adc059 100644 --- a/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -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 @@ public class NTLMAuthentication extends AuthenticationInfo { } } - 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 diff --git a/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c b/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c index db771d8cc..65f2cabda 100644 --- a/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c +++ b/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c @@ -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 #include #include "jni_util.h" +#include "jdk_util.h" #include -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 @@ JNIEXPORT jboolean JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthenticatio 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; } diff --git a/test/lib/testlibrary/jdk/testlibrary/net/URIBuilder.java b/test/lib/testlibrary/jdk/testlibrary/net/URIBuilder.java new file mode 100644 index 000000000..78844678e --- /dev/null +++ b/test/lib/testlibrary/jdk/testlibrary/net/URIBuilder.java @@ -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); + } + } +} diff --git a/test/sun/net/www/protocol/http/TestTransparentNTLM.java b/test/sun/net/www/protocol/http/TestTransparentNTLM.java new file mode 100644 index 000000000..d588500fa --- /dev/null +++ b/test/sun/net/www/protocol/http/TestTransparentNTLM.java @@ -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(); + } +} -- GitLab