Why does Java's URL class not recognize certain protocols? - java

URL u=new URL("telnet://route-server.exodus.net");
This line is generating :
java.net.MalformedURLException: unknown protocol: telnet
And I encounter similar problems with other URLs that begin with "news://"
These are URLs extracted from ODP, so I don't understand why such exceptions arise..

Issue
Java throws a MalformedURLException because it couldn't find a URLStreamHandler for that protocol. Check the javadocs of the constructors for the details.
Summary
Since the URL class has an openConnection method, the URL class checks to make sure that Java knows how to open a connection of the correct protocol. Without a URLStreamHandler for that protocol, Java refuses to create a URL to save you from failure when you try to call openConnection.
Solution
You should probably be using the URI class if you don't plan on opening a connection of those protocols in Java.

Sounds like there's no registered handler for the protocol "telnet" in your application. Since the URL class can be used to open a InputStream to URL it needs to have a registered handler for the protocol to do this work if you're to be allowed to create an object using it.
For details on how to add handlers see: http://docs.oracle.com/javase/7/docs/api/java/net/URLStreamHandlerFactory.html

You're getting that error because java doesn't have a standard protocol handler for telnet.

The simple answer is that it only does recognize certain protocols, and the remainder of the infinity of protocols is not recognized.

Related

Java (JDK1.8) is not setting server_name extension in SSL handshake when hostname has '_'

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet(url);
System.out.println(httpclient.execute(httpget));
I am using this programming snippet and using this with couple of urls. "https://abc.def.com/file.txt" and "https://ab_c.def.com/file.txt" (actual names i used exist - this is just an example). When i run the code with -Djavax.net.debug=ssl:handshake:data options set, I see _server_name_ extension is added only in case of abc.def.com and not in case of ab_c.def.com.
I am aware that java.net.URL package doesn't allow '_' in hostname. Is this a similar issue? Is there any workaround to get the SSL handshake include the hostname with '_'?
The answer is no. This wont work in java using the standard JDK libraries with HTTPS.
There virtually no "normal" Java way to work around this problem.
Other ideas:
ask the service owner to provide a domain name without the _.
dont use SSL/HTTPS. Most Java HTTP clients that are not doing strict checks will work with a hostname with an underscore in it. This is not a great solution if you are on the open internet
do use HTTPS but go direct to the IP address and disable HTTPS hostname validation. This is also a bad idea if you are on the open internet
introduce a MITM or forward proxy that can provide a HTTP endpoint to your service, but will do HTTPS over the untrusted parts of the network, (SSL onloading?)
just shell out to curl and read the resulting string, as described here on Baeldung. Be very careful here, as it's very easy to unwittingly open yourself up security issues like remote code execution
use jni to get to a network library that will allow the underscore - libcurl is an obvious candidate, but this will be significantly more work than the System.execute method, also possibly unsafe for other reasons (memory management, instability of badly written jni interop, not great for maintainability)
You could possibly try to fork the related URI / URL parsing classes in java.net to remove the check for the underscore. The problem with this is it's a massive hack, possibly of unbounded difficulty, could easily break all manner of things unintentionally and you might need to build your own version of the JDK as I have some recollection of java.net code being special for some reason in that you couldn't just chuck a patched class in ext/lib dir of the JVM (but I could be mixing that up with something else).
I will provide a hotfix.
In your /etc/hosts file, include a new entry without the underscore to the IP.
For example,
abc.com xx.xx.xx.xx
Then, use abc.com in your program.

Soap Connection timed out in Java client but not in SOAPUI

I created a soap client with wsimport and a given wsdl. I also used SoapUI to test the service. Using SoapUI I had no problem but when using my Java client I get
java.net.ConnectException: Connection timed out: connect
The default values I have in the requestContext are as follows
com.sun.xml.internal.ws.connect.timeout=100000
javax.xml.ws.service.endpoint.address=[fully qualified domain name endpoint]
com.sun.xml.internal.ws.request.timeout=100000
javax.xml.ws.soap.http.soapaction.use=null
com.sun.xml.internal.ws.client.ContentNegotiation=none
javax.xml.ws.soap.http.soapaction.uri=null
I've tried increasing the timeout but it still doesn't connect.
Has anyone else had a similar problem?
As you mentioned the problem is of proxy, it has been answered in below links.
How to use an HTTP proxy in java
Proxy settings in a java program
If you are using proxy with authentication then you have set authenticator along with the proxy. This is answered here.
Authenticated HTTP proxy with Java
EDIT:
As correctly mentioned by William Burnham, you have set to set the properties before calling them.
Morever, I recommend you to clear the property soon after getting response using System.clearProperty(key) as the property is set for complete instance of jvm till it is restarted and hence can cause problems for other outgoing connections.
The problem was I was behind a proxy. I did different tests and found that using a web browser (or SoapUI) I was able to access the resource but from the command line it wasn't working.
After much searching, it was a simple fix: either passing the property as a jvm argument or manually setting it in the code with System.setProperty("java.net.useSystemProxies", "true"). The JVM wasn't using the proxy on its own.
EDIT
As I used wsimport I have a jax-ws client. It's important that proxy settings be configured prior to instantiantion.
ANOTHER EDIT
If by chance you're having problems and you're using an application server to make the soap request through the proxy, you may have to specify java.net.useSystemProxies=true (or similar) in the server's configuration--for example catalina.properties if using tomcat.

TypeError: g.getResponseHeader is undefined

I have this code:
Connector conn = FrameworkUtil.getConnector(context, ALFRESCO_ENDPOINT_ID);
ConnectorContext c = new ConnectorContext(HttpMethod.POST);
c.setContentType("application/json");
Response res = conn.call("/slingshot/profile/userprofile", c,
new ByteArrayInputStream(buf.toString().getBytes()));
That makes a POST to the link: POST http://localhost:8080/share/service/components/profile/userprofile
But, I got the error:
TypeError: g.getResponseHeader is undefined
...unction(g){var b=g.argument.config;var
f=g.getResponseHeader["Content-Type"]||g....
In a search on the Internet, I saw that this can be a problem that is solved adding Content-Type with CORS.
Something like:
.header("Access-Control-Allow-Headers", "x-requested-with,Content-Type");
How can I do this in my code? With Connector or ConnectorContext I don't find a way to set the header...
Or if this is not the way to solve this, how can I solve this error?
I think you might have a few things configured incorrectly here, or you might be misunderstanding a few things. If you're making a remote connection to the ALFRESCO_ENDPOINT_ID then this typically means that you're trying to connect to the Alfresco Repository - and based on where you say you're trying to make the call from it would appear that this is in a Java-backed WebScript running within the Share application - is this correct?
If so, the URL that should be requested would actually be:
http://localhost:8080/alfresco/service/slingshot/profile/userprofile
Which would be equivalent to calling the following:
http://localhost:8080/share/proxy/alfresco/slingshot/profile/userprofile
(the second URL automatically proxies to the Alfresco enpoint).
If you have both the Alfresco Repository and Share running in the same server (which the use of the port 8080 implies you do) then you shouldn't be hitting CORS issues - unless you're trying to go from localhost to some remote location where the Alfresco Repository is running.
Share/Surf should be taking care of all of this for you - perhaps you can provide a bit more context on exactly what it is you're trying to do,
where the code is running (e.g. WebScript, Share, etc) and where you're trying to connect to?
This might help in best advising how to solve your main problem.

How to set “jsse.enableSNIExtension” to false only for a single HTTPURLConnection?

I currently have an application that would make HTTP post request to a lot of URLs. Some of the connections are failing with the following exception.
Exception in thread "main" javax.net.ssl.SSLProtocolException:
handshake alert: unrecognized_name at
sun.security.ssl.ClientHandshaker.handshakeAlert(ClientHandshaker.java:1410)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2004)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1113)
at
sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
at
sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
. . .
Hence, I want to set “jsse.enableSNIExtension” to false only for specific connections which throw the above mentioned exception.
How do I do it on an HTTPsURLConnection/SSLSocket level?
Code
URL url = new URL("https://artofskinmd.localgiftcards.com/");
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.connect();
I am trying to find a way to change the SSLParameters for the HttpsURLConnection object. But I am unable to find any setSSLParameters() method for setting an empty server names list. I am not able to find anything online on setting SSLParameters for HttpURLConnection, SSLContext etc
Obviously the site depends on SNI, otherwise it would not care about the name sent by the client in the SNI extension. This means that disabling the extension will probably not help, but instead you would then either get some handshake failure or some default site (and certificate) and probably not the site you have intended. To fix the problem you should not disable SNI but instead use the correct name, i.e. the name expected by the site.
Edit: This looks like both a bad server configuration together with a bug in Java7 and Java8. Access to the URL https://artofskinmd.localgiftcards.com/ will result in a unknown_name TLS alert warning which Java7 and Java8 wrongly consider fatal (same as the very old OpenSSL 0.9.8). Disabling SNI will actually help in this case, but there seems to be no way to disable SNI for a single HttpURLConnection object.
See
Java jar - no main manifest attribute
And this commit
https://github.com/Lekensteyn/OWASP-WebScarab/commit/8f2362eb021924cece9fb544f04bde5da7bfed4a

Java HTTP getResponseCode returns 200 for non-existent URL

I was expecting this code to return a 404, however it produces the output :
"Response code is 200"
Would it be possible to learn how to differentiate between existent and non-existent web pages . . . thanks so much,
try
{
// create the HttpURLConnection
URL url = new URL("http://www.thisurldoesnotexist");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
System.out.println("Response code is " + connection.getResponseCode());
}
EDIT: I see you've call openConnection() but not connect() - could that be the problem? I would expect getResponseCode() to actually make the request if it hasn't already, but it's worth just trying that...
That suggests you've possible got some DNS resolver which redirects to a "helper" (spam) page, or something like that.
The easiest way to see exactly what's going on here is to use Wireshark - have that up and capturing traffic (HTTP-only, to make life easier) and then run your code. You should be able to see what's going on that way.
Note that I wouldn't have expected a 404 - because that would involve being able to find a web server to talk to to start with. If you're trying to go to a host which doesn't involve, there shouldn't be an HTTP response at all. I'd expect connect() to throw an exception.
try adding a "connection.connect();" or look at the contents returned...
it could be a dns issue, ie: your dns is being sent to a parking place... for example: freedns does this.
You could:
Resolve the IP from the host of the page
Try to connect to port 80 on the resolved IP using plain sockets
This is a bit low level however and will add complexity since you will need to make a simple GET request through the socket. Then validate the response so you're sure that its actually a HTTP server running on port 80.
NMap might be able to help you here.
Ideally you should be getting this error:
java.net.UnknownHostException: www.thisurldoesnotexist
But it looks like your URL is resolved by you DNS provider.
For instance on my company's network running your code with URI "http://profile/" displays
the employee profile.
Please also check etc.home file if you are on windows to check if any settings have been changed.
Like #spgennard - I think this is most likely a DNS issue.
The URL you have chosen is owned by a DNS speculator.
The URL you have chosen is "parked" by a DNS provider.
Your ISP is messing with your DNS results to send your browser to some search page.
It is also possible that you are accessing the web via a proxy, and the proxy is doing something strange.
The way to diagnose this is to look at the other information in the HTTP responses you are getting, particularly the response body.

Categories

Resources