A small question regarding Netty and io.netty.handler.ssl.SslContext
In Tomcat and org.apache.http.ssl.SSLContexts, we have the possibility to perform the following:
HttpClient httpClient = HttpClients.custom()
.setSSLContext(SSLContexts.custom()
.loadKeyMaterial(someKeystorePropertlyInitialized)
.loadTrustMaterial(someTruststorePropertlyInitialized)
.build())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
(Appreciate if we can leave the fonts and not wrap inside a code block)
This can for instance fix issues such as Caused by: java.security.cert.CertificateException: No subject alternative DNS name matching xxx found
(This question is not about if NoopHostnameVerifier.INSTANCE is the proper way to fix this.)
My question is, what is the equivalent in Netty of .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE), without .trustManager(InsecureTrustManagerFactory.INSTANCE), because I have a real trust store, I just want to skip the host name, not everything
Maybe something with reactor.netty.http.client.HttpClient; HttpClient.create() ?
Actually, Netty has hostname verification turned off by default -- see this issue. It looks like the library you're using (reactor-netty) might have it turned on. There appears to be a similar issue on reactor-netty's github which points to the solution, but the code snippet provided seems to do more than what's necessary. Essentially, all you need is to access the SSLEngine from the SslHandler and make sure the endpoint identification algorithm is empty/null:
HttpClient.create().secure(
ssl -> ssl.sslContext(sslContext)
.handlerConfigurator(handler-> {
SSLEngine engine = handler.engine();
SSLParameters params = new SSLParameters();
// ... set other SSL params
params.setEndpointIdentificationAlgorithm(null);
})
);
I am working with orchid library and this is my code:
(...)
Proxy proxy = new Proxy(Proxy.Type.SOCKS,new InetSocketAddress("localhost",9150));
httpUrlConnetion = (HttpURLConnection) website.openConnection(proxy);
httpUrlConnetion.setRequestProperty("User-Agent","any user-agent");
httpUrlConnetion.setConnectTimeout(5000);
httpUrlConnetion.setReadTimeout(20000);
return Jsoup.parse(IOUtils.toString(httpUrlConnetion.getInputStream()));
And I am getting this warning:
WARNING: Your application is giving Orchid only an IP address. Applications that do DNS resolves themselves may leak information. Consider using Socks4a (e.g. via privoxy or socat) instead. For more information please see https://wiki.torproject.org/TheOnionRouter/TorFAQ#SOCKSAndDNS
I started on this answer to setup orchid.
I see this post but dind't get it working under http.
How to solve it? or any other way to easy use Tor with java?
Thanks!
In your mentioned thread you are using the URL class for resolving the URL to an IP adddress which will use the Native DNS-resolving technique (which is not tunneled through Tor).
You could use SilverTunnel-NG instead, this will also do the DNS-resolving over Tor.
Check out an example implementation here.
I am using WS to make a REST call to a server behind a proxy that required.
I tried to set proxyserver and port in application.conf and as JVM arg when I launch the application. But I keep getting "Error Code: 407 Proxy Authentication Required".
I tried to set ws.useProxyProperties at false and true, but it still doesn't work. I saw that it is a common problem, but no workaround has been published.
Do you have any idea?
Thanks
I managed to resolve this issue by using the dependancy
"com.ning" % "async-http-client" % "1.8.14"
And changing my code to
AsyncHttpClientConfig cf = new AsyncHttpClientConfig.Builder().setProxyServer(new
ProxyServer(host, port, user, pwd)).build();
c = new AsyncHttpClient(cf);
AsyncHttpClient.BoundRequestBuilder req = c.prepareGet("http://api.example.com/");
// and many other parameters ...
Applications such a Google's Chrome and IE can transparently handle Kerberos authentication; however I can not find a "simple" Java solution to match this transparency. All of the solutions I have found require the presence of a krb5.conf file and a login.conf file which nether of the above apps seem to require.
What is the best way to build a Java application with Kerberos SSO capabilities that just work?
[update]: to be clear I need a CLIENT side solution for creating tickets not validating them. Also, it seems that SPNEGO is the default "wrapper" protocol that will eventually delegate to Kerberos but I need to be able to handle the SPNEGO protocol as well.
There is now a simple solution for this using the Apache HTTP Components Client 4.5 or greater. This is still marked as experimental in 4.5 so your milage may vary, but this is working fine for me in an enterprise context.
In addition to the HC 4.5 client jars you will need to have the httpclient-win, jna and jna-platform jars on your classpath, as provided with http-component-client. You then construct a Kerberos enabled HC-client as follows:
CloseableHttpClient httpclient = WinHttpClients.createDefault();
Or using the builder:
HttpClientBuilder clientBuilder = WinHttpClients.custom();
Which can then be customised as required before building the client:
CloseableHttpClient client = clientBuilder.build();
This solution works without any external configuration, and most importantly solves the issue where the in-built JRE mechanism breaks for users with local Admin rights on Windows 7+. This is possible because the Kerberos ticket is being retrieved directly from the SSPI API via JNA, rather than going through the GSSAPI provided by the JRE.
Example code from the http-components team
This was all made possible by the good work of Daniel Doubrovkine Timothy Wall
and Ryan McKinley
Adding to David Roussels answer on url specific http based kerberos authentication:-
The reason why your code works is because your target SPN(server side principal) is configured to with HTTP/serverhostname.realm.com#DOMAIN.COM. In that case it will work because you are not explicitly setting the token. URLConnection internally sets a token with that SPN
1 Perform steps(from my previous answer) to get a subject
2 Use gss api init sec context to generate a context token. There are numerous tutorials out there for this step
3 Base 64 encode the token
4 Attach the token to urlconnection:-
URL url = new URL("http://myhost/myapp")
HttpURLConnection urlConn = (HttpURLConnection)url.openConnection(); =
urlConn.setRequestProperty("Authorization", "Negotiate " + encodedToken);
5 Implement a priviledged action:-
//this internally calls the getInputStream
public class PrivilegedGetInputStream implements PrivilegedExceptionAction<InputStream>
6 Wrap the whole thing in Subject.doAs
//use prev answer instructions to get subject
Subject.doAs(subject, new PrivilegedGetInputStream(urlConnection)
Oracle has an example using Java's SaslClient. I'm not a Java programmer, but when I pointed this out once to someone who is, they were able to make it work pretty quickly. It may still require a "conf" file somewhere (n.b. Kerberos uses environment variables, often starting with KRB5_, to know where to look for such files). Also note that Kerberos itself does not include a transport of any kind--your app needs to know how to send and receive the Kerberos payloads the way the server expects (and this is different depending on the server you are trying to authenticate with).
Edit: you edited your question, so here's a link related to SPNEGO in Java which might be of some use:
http://download.oracle.com/javase/6/docs/technotes/guides/security/jgss/lab/part5.html
You don't actually need to do anything. In Java 6, on a Windows client machine you can do this:
new URL("http://myhost/myapp").openStream();
And negotiate authentication just works. At least it does for me. And the server I tested on only supports Negotiate, not NTLM auth.
Ok if you want to avoid using a login.conf file you need to code differently:-
//define your own configuration
import javax.security.auth.login.Configuration;
public class CustomLoginConfiguration extends Configuration
//pass certain parameters to its constructor
//define an config entry
import javax.security.auth.login.AppConfigurationEntry;
private AppConfigurationEntry configEntry;
//define a map of params you wish to pass and fill them up
//the map contains entries similar to one you have in login.conf
Map<String, String> params = new HashMap<String, String>();
//define the configuration
configEntry = new AppConfigurationEntry(
"com.sun.security.auth.module.Krb5LoginModule",
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, params);
//implement getappconfig method
public AppConfigurationEntry[] getAppConfigurationEntry() {
return new AppConfigurationEntry[] { configEntry };
}
Now once you are done with this definition you can use this in you use this to fetch tickets from kdc
//get ticket in login context
LoginContext lc = null;
lc = new LoginContext("lc", null, callback, new CustomLoginConfiguration(argumentlist));
lc.login();
Now from here on you can fetch jaas subject and can basically do a ton of authentication stuff.
In case you need further pointers just leave a comment.
You can use system properties instead of config files to specify the KDC hostname and service name, but those things (at least) are mandatory....
Waffle will actually give you the information you need to set most of the properties, even if it won't get you a ticket. Look at the WindowsAuthProviderImpl class (the Waffle.chm help file shows the API).
I use JAAS do obtain a service ticket from Active Directory in two steps:
Use Krb5LoginModule to retrieve the cached TGT and add it to the Subject.
Use the Subject and GSS-API to retrieve a service ticket from the KDC.
There's a lot of good information and example code at The Java Way of Active Directory.
I created a small tool to simplify connecting with httpclient to kerberos, you might want to give it a try.
https://github.com/DovAmir/httpclientAuthHelper
DefaultHttpClient httpclient = new DefaultHttpClient();
AuthUtils.securityLogging(SecurityLogType.KERBEROS,true);
CredentialsUtils.setKerberosCredentials(client, new UsernamePasswordCredentials("xxx", "xxx"), "domain", "kdc");
client.executeMethod(httpget);
Use WAFFLE
Here's a good blog post on having a java client to use with Kerberos
http://sachithdhanushka.blogspot.com/2014/02/kerberos-java-client-configuration.html
It's not clicking how one is supposed to connect to a hosted Cloudant database using Ektorp. I'm using Ektorp 1.1 in Eclipse via the new m2eclipse Maven integration (which is pretty sweet). I'm struggling to find good CouchDB/Cloudant/Ektorp documentation other than javadocs.
I'm trying to get the sample Ektorp API example from their main page to work:
HttpClient httpClient = new StdHttpClient.Builder()
.host("localhost")
.port(5984)
.build();
CouchDbInstance dbInstance = new StdCouchDbInstance(httpClient);
CouchDbConnector db = new StdCouchDbConnector("mydatabase", dbInstance);
db.createDatabaseIfNotExists();
It doesn't matter what I use to build the httpClient with, I always get the UnknownHostException error below. I've tried these URLs for the host: https/http://cloudant.com/db/_session and https/http://[username].cloudant.com
What about the port number? Should the username and password be included in the StdHttpClient.Builder()?
Here's the full error - it's failing on the createDatabaseIfNotExists() call but I'm not confident the CouchDbConnector variable is correct.
Exception in thread "main" org.ektorp.DbAccessException: java.net.UnknownHostException: https://cloudant.com/db/_session
at org.ektorp.util.Exceptions.propagate(Exceptions.java:19)
at org.ektorp.http.StdHttpClient.executeRequest(StdHttpClient.java:104)
at org.ektorp.http.StdHttpClient.get(StdHttpClient.java:42)
at org.ektorp.http.RestTemplate.get(RestTemplate.java:21)
at org.ektorp.impl.StdCouchDbInstance.getAllDatabases(StdCouchDbInstance.java:61)
at org.ektorp.impl.StdCouchDbConnector.createDatabaseIfNotExists(StdCouchDbConnector.java:256)
at com.codegouge.examples.App.main(App.java:30)
Caused by: java.net.UnknownHostException: https://cloudant.com/db/_session
at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
at java.net.InetAddress$1.lookupAllHostAddr(InetAddress.java:850)
at java.net.InetAddress.getAddressFromNameService(InetAddress.java:1201)
at java.net.InetAddress.getAllByName0(InetAddress.java:1154)
at java.net.InetAddress.getAllByName(InetAddress.java:1084)
at java.net.InetAddress.getAllByName(InetAddress.java:1020)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:126)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:108)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:415)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554)
at org.ektorp.http.StdHttpClient.executeRequest(StdHttpClient.java:96)
So I was doing a couple things wrong. Using SSL requires additional parameters. Also, Ektorp 1.1.1 includes SSL-related bug fixes to 1.1.0. So this is my final HttpClient constructor:
HttpClient httpClient = new StdHttpClient.Builder()
.host("[username].cloudant.com")
.port(443)
.username("[username]")
.password("[password]")
.enableSSL(true)
.relaxedSSLSettings(true)
.build();
Also, be sure to update ektorp's dependency in pom.xml to look for version "1.1.1". I have a blog post covering this exercise here if interested.
You also can use the URL to connect with Ektorp:
JSONObject serviceAttr = val.getJSONObject(0);
JSONObject credentials = serviceAttr.getJSONObject("credentials");
httpClient = new StdHttpClient.Builder()
.url(credentials.getString("url"))
.build();
That's is easy way to connect. I found a tutorial to connect using Ektorp 1.4.2:
http://www.ibm.com/developerworks/java/library/j-hangman-app/index.html
I'm not very familiar with Ektorp, but you'll definitely need to get your username/password in there. I'd suggest creating the HttpClient with the following code:
HttpClient httpClient = new StdHttpClient.Builder()
.host("[username].cloudant.com")
.port(443)
.username("[username]")
.password("[password]")
.build();
I've changed the port to 443 (the default for HTTPS, which Cloudant listens on) and I've added a username and password. I don't see any way to let Ektorp know that you want to use HTTPS, but with luck that'll be handled internally.