I'm trying to communicate with a CUPS print-server that has "Encryption Required" set for all its connections. This means that, when you try to establish a connection to it, it asks to upgrade the connection to TLS-encrypted one, and neither Cups4j nor Jspi seem to be able to handle it.
Is there any way to connect to such a server from a Java application (using either these libraries or others)?
Your main problem is that CUPS/IPP is one of the rare protocols that use an HTTP to TLS upgrade, as described in RFC 2817. (https:// doesn't use that at all, see RFC 2818.) A consequence of that is that you'll find far less support in existing libraries for this upgrade.
In principle, upgrading a plain Socket into an SSLSocket isn't too difficult. However, since IPP relies on HTTP, it's likely that the libraries your library uses doesn't support this, since few HTTP libraries support RFC 2817.
I haven't looked at Cups4J, but Jspi clearly relies on Apache HTTP Client (probably version 3.x).
Support for RFC 2817 was discussed in 2011 on Apache HTTP Client mailing list, but it's not clear whether any of this made its way into the library. Anyway, the Jspi code is older than that, so it's fair to assume that it's not going to work.
A possible workaround:
Some IPP servers seem to support both TLS via an upgrade (RFC 2817) or via an initial connection (RFC 2818, the traditional https:// way). Perhaps yours does too. Check whether it listens to another port for TLS connections (e.g. by pointing an HTTPS client to it). (This could also be the same port if the server uses port unification.)
If this works, a quick patch to IppHttpConnection.java in Jspi should enable you to make it use https:// connections instead of http:// connections:
private static URI toHttpURI(URI uri) {
if (uri.getScheme().equals("ipp")) {
String uriString = uri.toString().replaceFirst("ipp", "http");
I'm not sure if ipps:// is standard, but you could use the same trick and replace ipps:// with https:// in the scheme. The rest should automatically be handled by the underlying HTTP library. (You might have to make sure your certificate is trusted too, but that's a different problem.)
Related
I have a Spring application inside a tomcat 8 container, this application has both local (intranet) and remote (internet) service. I would like to serve local services with simple HTTP and remote with HTTPS, is it possibile editing tomcat configuration and without filter requests inside the application?
I should distinguish local from remote requests by its ip address.
You shouldn't need to. Your local network should be protected by a firewall, and you simply configure the firewall to only allow the secure port through.
Local traffic from the intranet doesn't go through the firewall, so it can access the HTTP port (80, 8080, ...).
External traffic comes in through the firewall, and it will block the HTTP port and allow the HTTPS port (443, 8443, ...).
Often with HTTPS, you don't even let Tomcat handle that, but instead put IIS (Windows) or Apache (Linux) in front of it. In that case you only have an AJP connector on localhost, and nobody can talk directly to Tomcat. The frontend web server will then do the required filtering and SSL/TLS handshake.
If you have anything that's worth using https for, I'd opt to go https all the way: Otherwise you'll sooner or later have information leaks because you've missed some crucial part of configuration. HTTPS is no black magic anymore, performance impact is low if exists it at all.
In fact, the typical usecase that I see described is exactly opposite to yours: Intranet usage is typically more protected than internet access (which is thought to be anonymous, but it depends on the nature of the site). However, an Intranet is typically authenticated (more so than the internet side, typically) and I'd expect it to be quite important to protect the authentication. The only mixed-mode solution (http/https) that I could come up with for this situation is: Use HSTS as soon as a user logs in, don't bother otherwise.
You're asking for the opposite of what I typically see - but my actually preferred solution (in all cases) is: Force https everywhere, use HSTS. And don't worry any more. Easier to maintain, Easier to setup and hard to get wrong.
I have an GUI which is designed in JAVA and act as an client, and can communicate remotely to an server which is written in C/C++. Communication between them is made through Sockets. However the messages sent are not encrypted and is vulnerable to man-in-the-middle attacks. I was wondering what the best solution will be to protect the communication and wanted to implement SSL. Is it possible to do so, and if yes, what toolkit I should look into.
Java contains an SSL implementation called JSSE. See the Javadoc for the javax.net.ssl package. There is also a tutorial, and several examples are provided with the JDK.
You might not even need to modify the server at all. You could just stick stunnel in front of it.
A warning: With TLS/SSL you face a whole bunch of additional error conditions that you might need report or log, especially concerning certificates (wrong, expired, unable to verify due to networking / DNS issues)
I am having a problem with a signed Java applet which performs simple HTTPS requests to our server (using Java's URL, Connection classes). Everything looks ok for majority of the clients. However, we do have several clients under corporate network, which are behind a proxy that requires authentication (possibly windows-logon-based authentication)). And for these clients we often hear such feedback like:
The application behaves extremely slow though our network speed is 20mbps.
20mbps connection is a huge speed for our application to work perfectly.
So my first question specifically the following:
1) Can it be the case that proxy analyses the content of our requests and thus impacts the performance of the app. And could it be only a Java-specific problem ?
The next part is about Java and Java applets specifically.
From forums I know there is a problem with Java selecting the right proxy configured in Browser. Sometimes Java applet fails to detect the proxy configured in IE, and the only solution is to configure it also in Java's Control Panel.
Having said this, the next question is:
2) Taking into account that direct connection for the corporate clients is not allowed and Java Control Panel is not properly configured, could that be the case that Java plugin selects another - wrong proxy, thru which it eventually access to the servers and thus resulting very low performance ?
I also have tried to use Apache's HttpClient (http://hc.apache.org/httpcomponents-client-ga/), to check how it performs under such environment. I have configured the client as specified in Apache tutorial to automatically get the JRE's proxy:
httpclient = new DefaultHttpClient();
ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(
httpclient.getConnectionManager().getSchemeRegistry(),
ProxySelector.getDefault());
httpclient.setRoutePlanner(routePlanner);
And what we faced is an authentication required error (407) when we try to execute requests via Apache's httpclient. Specifically407 proxy authentication required. the ISA server requires
authorisation to fulfill the request
So the last question is about this differences between Apache and Java's client.
3) How Java Applet chooses the proxy ? and How Apache Client's selection logic differs from that of Java's ?
Please share any strongly confirmed experience you might find out could be helpful for my situation.
Thanks in advance.
3) How Java Applet chooses the proxy ?
Default behaviour:
Applet checks control panel\java\ network\network proxy settings
and uses the proxy according to the configuration in there.
Setting system properties for an applet does not works.
i.e:
System.setProperty("java.net.useSystemProxies","true");
System.setProperty("http.proxyHost", "1.1.1.1");
System.setProperty("http.proxyPort", "8080");
If you want to alter the proxy selection for an applet.
then you can use ProxySelector class.
also check out this question how-to-set-http-proxy-in-an-applet you may find it useful.
I have a web-service endpoint and a http connector on port X.
At some point this endpoint needs to switch to https, but on the same port!
(I know this is not the normal way of doing things, but this is what my clients expect from an old server they are using...)
Is there a way to do it in tomcat?
This is not possible with Tomcat.The HTTPS connector will accept SSL connection only.
We have such a proxy developed in house. It's not that hard to do. You just need to check the first incoming packet. Looking for the pattern of SSL handshake. We only look for CLIENT_HELLO. Once you figure out the protocol, you can forward the request accordingly.
This is really ugly. You shouldn't do it if all possible. We have to do it because the legacy clients do this and it's impossible to upgrade them all.
There is such a thing as HTTPS upgrade, whereby a plaintext HTTP connection is upgraded to HTTP by mutual agreement after it has been formed. Is that what you mean? If so, Tomcat doesn't seem to support it out of the box, and neither does Java out of the box either. You can probably write yourself a Tomcat Connector that will do it; on the client end you have a more interesting problem ;-)
But I would ask why? Ports aren't so expensive that you can't use two.
You don't need to run the HTTP & HTTPS on same port, Configure the Tomcat to redirect requests to HTTPS in server.xml file.
well I wonder why they are NOT usually on the same port! wouldn't that be easier?
the reason is probably that related Java APIS (javax.net.ssl) don't allow that; you must have different server sockets. are there any alternative SSL impls for Java? I'm not aware of any.
I have to work on an old 1.3 JVM and I'm asked to create a secure connection to another server. Unfortunately the HttpsURLConnection only appears sinc JVM 1.4.
Is there another way to create a secure connection? Is there a library that I could you to add this fonctionnality?
You need to install the Java Secure Socket Extension (JSSE), which used to be required because Sun wouldn't ship it with the JDK because of comedy export restrictions. I had a look on Sun's web site, but the JDK 1.3 instructions are preving elusive. Bear in mind that JDK 1.3 is now end-of-lifed by Sun, so they may not have any information any more.
http://hc.apache.org/httpclient-3.x/sslguide.html
Check out the BouncyCastle implementation. It works all the way down to Java 1.1 and J2ME.
If JSSE doesn't work out for you (from #skaffman's answer, it may be hard to find documentation), you may want to look into some sort of a proxy. You could set up a daemon running on the same local machine (or trusted network), which then forwards the requests over HTTPS to the final end point. You could write this proxy server using a more modern JVM. Your legacy system would then point to the proxy rather than the real service.
Of course, if, by chance, you also have control over the final end point, you could perhaps just put both servers on a VPN.
You might be able to use JSSE.
skaffman links to the SSL guide for jakarta commons HttpClient. HttpClient is a good library for dealing with http.