eclipse / ecf

ECF project repository
6 stars 14 forks source link

httpclient5 lacks kerberos support #73

Closed christophvw closed 2 months ago

christophvw commented 10 months ago

httpclient5 lacks kerberos support for proxy authentication:

https://github.com/eclipse/ecf/blob/master/providers/bundles/org.eclipse.ecf.provider.filetransfer.httpclient5/src/org/eclipse/ecf/internal/provider/filetransfer/httpclient5/HttpClientProxyCredentialProvider.java

} else if ("negotiate".equalsIgnoreCase(authscope.getSchemeName())) { Trace.trace(Activator.PLUGIN_ID, "SPNEGO is not supported, if you can contribute support, please do so.");

This becomes more important as Microsoft plans to remove NTLM support in future Windows 11 builds. https://techcommunity.microsoft.com/t5/windows-it-pro-blog/the-evolution-of-windows-authentication/ba-p/3926848

https://bugs.eclipse.org/bugs/show_bug.cgi?id=561175

scottslewis commented 10 months ago

@christophvw thanks for opening this issue. Not sure if you were aware, but Eclipse is in the process of moving to the JRE-provided impl of httpclient as per https://github.com/eclipse-platform/eclipse.platform.releng.aggregator/pull/1389#issuecomment-1734270639 rather than using httpclient5. Have you checked whether the javahttpclient provider has this capability?

scottslewis commented 9 months ago

@laeubi please take a look at this as it likely means further changes to javahttpclient

laeubi commented 9 months ago

@scottslewis do you think we should add a

Trace.trace(Activator.PLUGIN_ID, "SPNEGO is not supported, if you can contribute support, please do so.");

to javahttpclient as well ;-)

In general this describes how to do kerberos auth in java http subsystem:

https://docs.oracle.com/en/java/javase/11/security/part-vi-http-spnego-authentication.html#GUID-05B34286-D0B6-4C35-B0BF-C98CD9F7E1D2

Main problem is that I don not have any kerberos proxy ... so the very first thing I think would be to have some kind of testcase so one can work on it.

scottslewis commented 9 months ago

@scottslewis do you think we should add a

Trace.trace(Activator.PLUGIN_ID, "SPNEGO is not supported, if you can contribute support, please do so.");

to javahttpclient as well ;-)

I think it would be more direct to just state that you are not able to do it yourself and so a contribution is likely required (or some other support path is required).

laeubi commented 9 months ago

I once implemented kerberos auth and there are some impls out there but right now I have no kerberos infrastructure to use :-\

scottslewis commented 9 months ago

I once implemented kerberos auth and there are some impls out there but right now I have no kerberos infrastructure to use :-\

Hmm...well, that sounds familiar (not having means to test proxy environments in ECF). I hope that someone recognizes the history here and does something more than to point at the community (which is doing quite a lot already IMHO).

scottslewis commented 2 months ago

It appears that @laeubi isn't going to address this deficiency in the current (java jre-based) httpclient provider. Until someone shows up to do the necessary work, closing.

christophvw commented 2 months ago

@laeubi using Kerberos on Windows with Java 11 is much easier:

-Dsun.security.jgss.native=true -Djavax.security.auth.useSubjectCredsOnly=false

done. No need for a keytab.

https://docs.oracle.com/en/java/javase/11/security/accessing-native-gss-api.html https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-6722928

christophvw commented 2 months ago

https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/19fb8f93c59dfd791f62d41f332db9e306bc1422/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java#L46

hmm - does this mean this is only supported by HttpURLConnection and not by HttpClient?

laeubi commented 2 months ago

@christophvw as mentioned the main problem is that I have no kerberos infrastructure otherwise one could simply test if it works OOTB...

christophvw commented 2 months ago

It does not work out of the box

I just downloaded Eclipse 2024-03 - and edited the eclipse.ini

changed: -Dorg.eclipse.ecf.provider.filetransfer.excludeContributors=org.eclipse.ecf.provider.filetransfer.httpclient5

added: -Djavax.net.ssl.trustStoreType=WINDOWS-ROOT -Dsun.security.jgss.native=true -Djavax.security.auth.useSubjectCredsOnly=false

org.eclipse.equinox.p2.core.ProvisionException: HTTP Proxy Authentication Required: https://google.de/content.xml at org.eclipse.equinox.internal.p2.repository.CacheManager.createCache(CacheManager.java:250) at org.eclipse.equinox.internal.p2.metadata.repository.SimpleMetadataRepositoryFactory.getLocalFile(SimpleMetadataRepositoryFactory.java:69) at org.eclipse.equinox.internal.p2.metadata.repository.SimpleMetadataRepositoryFactory.load(SimpleMetadataRepositoryFactory.java:89) at org.eclipse.equinox.internal.p2.metadata.repository.MetadataRepositoryManager.factoryLoad(MetadataRepositoryManager.java:63) at org.eclipse.equinox.internal.p2.repository.helpers.AbstractRepositoryManager.loadRepository(AbstractRepositoryManager.java:791) at jdk.internal.reflect.GeneratedMethodAccessor48.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.eclipse.oomph.util.ReflectUtil.invokeMethod(ReflectUtil.java:119) at org.eclipse.oomph.p2.internal.core.CachingRepositoryManager.loadRepository(CachingRepositoryManager.java:448) at org.eclipse.oomph.p2.internal.core.CachingRepositoryManager.loadRepository(CachingRepositoryManager.java:231) at org.eclipse.oomph.p2.internal.core.CachingRepositoryManager$Metadata.loadRepository(CachingRepositoryManager.java:520) at org.eclipse.equinox.internal.p2.metadata.repository.MetadataRepositoryManager.loadRepository(MetadataRepositoryManager.java:110) at org.eclipse.equinox.internal.p2.metadata.repository.MetadataRepositoryManager.loadRepository(MetadataRepositoryManager.java:105) at org.eclipse.equinox.p2.ui.ProvisioningUI.loadMetadataRepository(ProvisioningUI.java:498) at org.eclipse.equinox.internal.p2.ui.model.MetadataRepositoryElement.getMetadataRepository(MetadataRepositoryElement.java:138) at org.eclipse.equinox.internal.p2.ui.model.MetadataRepositoryElement.getRepository(MetadataRepositoryElement.java:127) at org.eclipse.equinox.internal.p2.ui.model.MetadataRepositoryElement.getQueryable(MetadataRepositoryElement.java:120) at org.eclipse.equinox.internal.p2.ui.QueryProvider.getQueryDescriptor(QueryProvider.java:92) at org.eclipse.equinox.internal.p2.ui.model.QueriedElement.fetchChildren(QueriedElement.java:103) at org.eclipse.equinox.internal.p2.ui.model.MetadataRepositoryElement.fetchChildren(MetadataRepositoryElement.java:86) at org.eclipse.equinox.internal.p2.ui.model.RemoteQueriedElement.fetchDeferredChildren(RemoteQueriedElement.java:38) at org.eclipse.ui.progress.DeferredTreeContentManager$1.run(DeferredTreeContentManager.java:215) at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63) Caused by: org.eclipse.ecf.filetransfer.BrowseFileTransferException: Proxy Authentication Required at org.eclipse.ecf.provider.filetransfer.httpclientjava.HttpClientFileSystemBrowser.runRequest(HttpClientFileSystemBrowser.java:292) at org.eclipse.ecf.provider.filetransfer.browse.AbstractFileSystemBrowser$DirectoryJob.run(AbstractFileSystemBrowser.java:71) ... 1 more

christophvw commented 2 months ago

I did a quick test:

I used the following JRE options: -Djavax.net.ssl.trustStoreType=WINDOWS-ROOT -Dsun.security.jgss.native=true -Djavax.security.auth.useSubjectCredsOnly=false

            String urlString = "https://google.de";

        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy", 8080));
        try {
            HttpURLConnection conn = (HttpURLConnection) new URL(urlString).openConnection(proxy);
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { // success
                BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String inputLine;
                StringBuffer response = new StringBuffer();

                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();

                // print result
                System.out.println(response.toString());
            }       
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

-> Works with Kerberos out of the box

    HttpClient client = HttpClient.newBuilder()
                .version(Version.HTTP_2)
                .proxy(ProxySelector.of(new InetSocketAddress("proxy", 8080)))
                .build();

        HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create("http://google.com"))
              .build();
        client.sendAsync(request, BodyHandlers.ofString())
              .thenApply(HttpResponse::body)
              .thenAccept(System.out::println)
              .join();

-> does not

christophvw commented 2 months ago

https://bugs.java.com/bugdatabase/view_bug?bug_id=JDK-8334079