IntelliJ: Why java.net.InetAddress is deprecated Class? - java

I've got a some problem. My program cant't run, throws: nullPointException. On other IDE it's running.
One day ago I just click something, I don't know what that was :(
Now this is look like this:
InetAddress localHost = Inet4Address.getLocalHost();
But InetAddress is strike throuh.
Please help, how can I undo this.

This method is not deprecated in the version up to Java 9
https://docs.oracle.com/javase/9/docs/api/java/net/InetAddress.html#getLocalHost--
I have seen this fail on mis-configured machines. e.g. you have an invalid hosts file, though it shouldn't ever throw a NullPointerException AFAIK.
What I do is catch UnknownHostException and use "localhost" instead if this fails.
https://github.com/OpenHFT/Chronicle-Core/blob/master/src/main/java/net/openhft/chronicle/core/OS.java#L133
private static String getHostName0() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
return "localhost";
}
}

Related

How to establish a FTPS data connection to a FileZilla Server 1.2.0

It is a known problem to use the Java FTPSClient of Apache commons-net with session resumption. Session resumption is a security feature which a FTPS server can require for data connections. The Apache FTPSClient does not support session resumption, and the JDK APIs make it hard to build a custom implementation. There are a couple of workarounds using reflection, see e.g. this answer and this commons-net bug entry.
I use such a workaround (see snipped below) in JDK 11 and tested it against a local FileZilla Server. It works with FileZilla Server 0.9.6, but it doesn't with FileZilla Server 1.2.0, which is the latest version at the time of writing. With that version, when trying to establish a data connection, the server responds with:
425 Unable to build data connection: TLS session of data connection not resumed.
As I said, FileZilla Server 0.9.6 is fine with how I do session resumption, and I made sure that the setting for requiring session resumption is activated.
In FileZilla Server 1.2.0, such settings are now set implicitly and cannot be changed via the GUI, maybe not at all. Are there some server settings that I can tweak for this to work? Or is it an issue with how I implemented the workaround? Does anyone experience similar issues?
This is the workaround I am using:
public class FTPSClientWithSessionResumption extends FTPSClient {
static {
System.setProperty("jdk.tls.useExtendedMasterSecret", "false");
System.setProperty("jdk.tls.client.enableSessionTicketExtension", "false");
}
#Override
protected void _connectAction_() throws IOException {
super._connectAction_();
execPBSZ(0);
execPROT("P");
}
#Override
protected void _prepareDataSocket_(Socket socket) throws IOException {
if (useSessionResumption && socket instanceof SSLSocket) {
// Control socket is SSL
final SSLSession session = ((SSLSocket)_socket_).getSession();
if (session.isValid()) {
final SSLSessionContext context = session.getSessionContext();
try {
final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
sessionHostPortCache.setAccessible(true);
final Object cache = sessionHostPortCache.get(context);
final Method putMethod = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
putMethod.setAccessible(true);
Method getHostMethod;
try {
getHostMethod = socket.getClass().getMethod("getPeerHost");
}
catch (NoSuchMethodException e) {
// Running in IKVM
getHostMethod = socket.getClass().getDeclaredMethod("getHost");
}
getHostMethod.setAccessible(true);
Object peerHost = getHostMethod.invoke(socket);
InetAddress iAddr = socket.getInetAddress();
int port = socket.getPort();
putMethod.invoke(cache, String.format("%s:%s", peerHost, port).toLowerCase(Locale.ROOT), session);
putMethod.invoke(cache, String.format("%s:%s", iAddr.getHostName(), port).toLowerCase(Locale.ROOT), session);
putMethod.invoke(cache, String.format("%s:%s", iAddr.getHostAddress(), port).toLowerCase(Locale.ROOT), session);
}
catch (Exception e) {
throw new IOException(e);
}
}
else {
throw new IOException("Invalid SSL Session");
}
}
}
}
The address under which the socket is cached is determined using getPeerHost, getInetAddress().getHostName(), and getInetAddress().getHostAddress(). I tried several combinations of doing or not doing these three, but I always get the same result.
Edit:
Here is a screenshot of the server logs of the full session:
As stated in this StackOverflow post it is possible to tell the JVM that only TLS 1.2 should be used.
Here is the link to the original answer which worked for me: command for java to use TLS1.2 only
You have to add a command line parameter at the start of the JVM in this case this is: java -Djdk.tls.client.protocols=TLSv1.2 -jar ... <rest of command line here>
This simple parameter worked for me, now I can connect and transfer data from a FTP-Server wich runs FileZilla FTP-Server 1.3.0

SNI client-side mystery using Java8

I have an Apache web server that runs several TLS virtualhosts with different certs and SNI.
I can access the various virtual hosts just fine using curl (presumably SNI makes it work). I can also access them fine with a little command-line Java program that basically just openConnection()s on a URL.
In my Tomcat application, the basic same client-side code accesses the same Apache server as a client, but always ends up with the default cert (defaulthost.defaultdomain) instead of the cert of the virtual host that was specified in the URL that it attempts to access. (This produces a SunCertPathBuilderException -- basically it can't verify the certificate path to the cert, which of course is true as it is a non-official cert. But then the default cert should not be used anyway.)
It's just as if SNI had been deactivated client-side in my application / Tomcat. I am at a loss why it should behave differently between my app and the command-line; same JDK, same host etc.
I found property jsse.enableSNIExtension, but I verified that it is set to true for both cases. Questions:
Any ideas, even wild ones, why these two programs behave differently?
Any ideas how I would debug this?
This is Arch Linux on 86_64, JDK 8u77, Tomcat 8.0.32.
This answer comes late, but we just have hit the problem (I can't believe it, it seems a very big bug).
All what it said seems true, but it's not default HostnameVerifier the culprit but the troubleshooter. When HttpsClient do afterConnect first try to establish setHost (only when socket is SSLSocketImpl):
SSLSocketFactory factory = sslSocketFactory;
try {
if (!(serverSocket instanceof SSLSocket)) {
s = (SSLSocket)factory.createSocket(serverSocket,
host, port, true);
} else {
s = (SSLSocket)serverSocket;
if (s instanceof SSLSocketImpl) {
((SSLSocketImpl)s).setHost(host);
}
}
} catch (IOException ex) {
// If we fail to connect through the tunnel, try it
// locally, as a last resort. If this doesn't work,
// throw the original exception.
try {
s = (SSLSocket)factory.createSocket(host, port);
} catch (IOException ignored) {
throw ex;
}
}
If you use a custom SSLSocketFactory without override createSocket() (the method without parameters), the createSocket well parametrized is used and all works as expected (with client sni extension). But when second way it's used (try to setHost en SSLSocketImpl) the code executed is:
// ONLY used by HttpsClient to setup the URI specified hostname
//
// Please NOTE that this method MUST be called before calling to
// SSLSocket.setSSLParameters(). Otherwise, the {#code host} parameter
// may override SNIHostName in the customized server name indication.
synchronized public void setHost(String host) {
this.host = host;
this.serverNames =
Utilities.addToSNIServerNameList(this.serverNames, this.host);
}
The comments say all. You need to call setSSLParameters before client handshake. If you use default HostnameVerifier, HttpsClient will call setSSLParameters. But there is no setSSLParameters execution in the opposite way. The fix should be very easy for Oracle:
SSLParameters paramaters = s.getSSLParameters();
if (isDefaultHostnameVerifier) {
// If the HNV is the default from HttpsURLConnection, we
// will do the spoof checks in SSLSocket.
paramaters.setEndpointIdentificationAlgorithm("HTTPS");
needToCheckSpoofing = false;
}
s.setSSLParameters(paramaters);
Java 9 is working as expected in SNI. But they (Oracle) seem not to want fix this:
https://bugs.openjdk.java.net/browse/JDK-8072464
https://bugs.openjdk.java.net/browse/JDK-8144566
and many more
After some hours of debugging the JDK, here is the unfortunate result. This works:
URLConnection c = new URL("https://example.com/").openConnection();
InputStream i = c.getInputStream();
...
This fails:
URLConnection c = new URL("https://example.com/").openConnection();
((HttpsURLConnection)c).setHostnameVerifier( new HostnameVerifier() {
public boolean verify( String s, SSLSession sess ) {
return false; // or true, won't matter for this
}
});
InputStream i = c.getInputStream(); // Exception thrown here
...
Adding the setHostnameVerifier call has the consequence of disabling SNI, although the custom HostnameVerifier is never invoked.
The culprit seems to be this code in sun.net.www.protocol.https.HttpsClient:
if (hv != null) {
String canonicalName = hv.getClass().getCanonicalName();
if (canonicalName != null &&
canonicalName.equalsIgnoreCase(defaultHVCanonicalName)) {
isDefaultHostnameVerifier = true;
}
} else {
// Unlikely to happen! As the behavior is the same as the
// default hostname verifier, so we prefer to let the
// SSLSocket do the spoof checks.
isDefaultHostnameVerifier = true;
}
if (isDefaultHostnameVerifier) {
// If the HNV is the default from HttpsURLConnection, we
// will do the spoof checks in SSLSocket.
SSLParameters paramaters = s.getSSLParameters();
paramaters.setEndpointIdentificationAlgorithm("HTTPS");
s.setSSLParameters(paramaters);
needToCheckSpoofing = false;
}
where some bright mind checks whether the configured HostnameVerifier's class is the default JDK class (which, when invoked, just returns false, like my code above) and based on that, changes the parameters for the SSL connection -- which, as a side effect, turns off SNI.
How checking the name of a class and making some logic depend on it is ever a good idea escapes me. ("Mom! We don't need virtual methods, we can just check the class name and dispatch on that!") But worse, what in the world does SNI have to do with the HostnameVerifier in the first place?
Perhaps the workaround is to use a custom HostnameVerifier with the same name, but different capitalization, because that same bright mind also decided to do case-insensitive name comparison.
'nuff said.
This is a Java 8 bug (JDK-8144566) fixed by 8u141. See Extended server_name (SNI Extension) not sent with jdk1.8.0 but send with jdk1.7.0 for more.

JSP: new Socket ("www", 80); stopped working after years of working OK

In a JSP app, in Tomcat, the following code used to produce the whole address of the page (from this answer):
String myUrl = "no network";
try {
Socket s = new Socket("www", 80);
myUrl = "http://"+s.getLocalAddress().getHostAddress()+":"+request.getLocalPort()+request.getRequestURI();
s.close();
} catch (Exception ex) {
} finally {
}
After that miUrl would have the folowing value (not the real IP addr): http://111.101.101.2:8080/mypage.jsp
It has been working for several years.
A week ago miUrl began having "no network" as value, indicating that an exception happened.
I issued ex.printStackTrace() and is says: java.net.UnknownHostException: www
Creating a socked with the literal "www" used to work, now out of a sudden it stopped working.
Question:
What's the technical reason why it worked for years?
What's the technical reason why it stopped working all of a sudden?
What would be the best way to programatically produce the whole address of any JSP page, that is not error-prone?
EDIT: It's a file-sharing app, running in the users's workstation, I want users to be able to copy the address to share links with others, and http://localhost:8080/downloadpage.jsp (as shown in address field of browser) is no good for sharing. It would help if you show me how to get that same info without the socket hack.
Like Beau Grantham said in the comment, there's a decent chance that this is a DNS issue. Try
$ ping www
and see if it resolves to anything. If you get
$ ping www
ping: cannot resolve www: Unknown host
$
then that's your issue.
I ran this locally and got:
~$ java TestResolve
java.net.UnknownHostException: www
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:184)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at java.net.Socket.<init>(Socket.java:434)
at java.net.Socket.<init>(Socket.java:211)
at TestResolve.main(TestResolve.java:7)
(I wouldn't expect this to be a hosts file since everybody is able to use the URL. Anyway 'www' is the sort of thing that you'd manage using DNS.)
As far as programmatically generating URLs, try
InetAddress.getLocalHost().getHostName()
if you're OK with a hostname. The other peers can probably resolve that. Otherwise
InetAddress localhost = InetAddress.getLocalHost();
InetAddress[] ips = InetAddress.getAllByName(localhost.getHostName());
Here you'll get a list of IPs for the host in question, corresponding to different interfaces. You might have to choose one based on the subnet, which presumably you could configure into the app.
Solved the IP addr part without using a socket.
public String getIP(){
String ip="no network";
try {
Enumeration<NetworkInterface> n = NetworkInterface.getNetworkInterfaces();
outmost:
for (; n.hasMoreElements();)
{
NetworkInterface e = n.nextElement();
Enumeration<InetAddress> a = e.getInetAddresses();
for (; a.hasMoreElements();)
{
InetAddress addr = a.nextElement();
if (addr instanceof Inet4Address){ // return the first IPv4 addr (127.0.1.1 is always last)
if (addr.isSiteLocalAddress()){
ip=addr.getHostAddress();
break outmost;
}
}
}
}
} catch (UnknownHostException e1) {
} catch (SocketException e) {
}
return ip;
}
Then
String miUrl = "http://"+getIP()+":"+request.getLocalPort()+request.getRequestURI();

Port in use by "Port currently not owned"

I'm getting some strange results from the javax.comm library. I'm running this constructor:
SerialPort port;
public Scale(String porttotry) {
CommPortIdentifier cpi = null;
try {
cpi = CommPortIdentifier.getPortIdentifier(porttotry);
//Open Port and establish stream
log.trace("Opening CPI: {}", cpi.getCurrentOwner());
port = (SerialPort) cpi.open("My Application", 2000);
log.trace("CPI opened");
//... configuration stuff
} catch (PortInUseException ex) {
log.error("{}: Port in use by {}", porttotry, cpi.getCurrentOwner());
} catch (NoSuchPortException ex) {
log.error("No such port as {}", porttotry);
}
}
What's really strange is the fact that CommPortIdentifier.open(String, int) appears to be throwing a PortInUseException when the port is not in use. The log output says
TRACE [10:19:03.147] Scale:72 Opening CPI: Port currently not owned
ERROR [10:19:05.149] Scale:98 COM4: Port in use by Port currently not owned
The first log line means to me that open() should succeed, but it doesn't. I've connected to this device before and gotten data from it. This is a strange new error. Does anybody have any idea what could cause this? My gut tells me that this is some tricky thing with Windows having possession issues. I'm open to any ideas and I'll provide more information if you need it.
I can't speak for exactly why this strange error occurred, but I did find something of a solution. It seems that I was correct in assuming it was Windows being possessive. When I shut down, unplugged my device, powered on with the device still unplugged, then connected the device, the PortInUseException disappeared.

Using InetAddress to get own IP

I have an issue were if I try to InetAddress.getLocalHost() or even InetAddress.getByName(String host) it throws an exception every time even for a known website like nba.com I am a bit confused FYI the target device is an android 4.1.1 GS3 and wifi and mobile network are on. Code below
try{
InetAddress ownIP=InetAddress.getLocalHost();
System.out.println("IP of my Android := "+ownIP.getHostAddress());
}catch (Exception e){
System.out.println("Exception caught ="+e.getMessage());
String t = e.getMessage() + "yes";
}
Below is the System.out
03-12 18:59:52.636: I/System.out(18996): Exception caught =null
Thanks in advance
I use a tricky method to get my own IP. you can see whether it helps you
String getIP() {
try {
Socket socket = new Socket("google.com", 80);
return socket.getLocalAddress().getHostAddress();
} catch (Exception e) {
}
}
I believe I have found out what my issue was basically I guess you are not allowed to perform any network operations in the Main thread for android this was optional before and is now required for Honeycomb (API 11) and up below is the comment as per google specs.
"To prevent blocking the main user interface thread, Google recommends using the AsyncTask class from the android.os package:"
So all I was create a new class NetTask which extends AsyncTask and perform all network applications so now my code is working. IDK if everybody else knew that but I figured I would post this in case any newbs like me were still looking for a solution :) !!!
Thanks

Categories

Resources