Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

javax.net.ssl.SSLException: closing inbound before receiving peer's close_notify #531

Closed
akabanov57 opened this issue Sep 16, 2019 · 17 comments

Comments

@akabanov57
Copy link

akabanov57 commented Sep 16, 2019

Hello,
I try to use Ice with ssl support in OSGi container. I use OpenJDK 12.0.2, Apache Felix, Ice for java.
When I stop server on client side I get an exception:

javax.net.ssl|ERROR|29|Ice.ThreadPool.Client-0|2019-09-16 22:03:40.510 MSK|TransportContext.java:312|Fatal (INTERNAL_ERROR): closing inbound before receiving peer's close_notify (
"throwable" : {
  javax.net.ssl.SSLException: closing inbound before receiving peer's close_notify
  	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:133)
  	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
  	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:307)
  	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:263)
  	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:254)
  	at java.base/sun.security.ssl.SSLEngineImpl.closeInbound(SSLEngineImpl.java:733)
  	at com.zeroc.IceSSL.TransceiverI.close(TransceiverI.java:147)
  	at com.zeroc.Ice.ConnectionI.finish(ConnectionI.java:1447)
  	at com.zeroc.Ice.ConnectionI.finished(ConnectionI.java:1378)
  	at com.zeroc.IceInternal.ThreadPool$FinishedWorkItem.execute(ThreadPool.java:37)
  	at com.zeroc.IceInternal.ThreadPoolWorkQueue.message(ThreadPoolWorkQueue.java:74)
  	at com.zeroc.IceInternal.ThreadPool.run(ThreadPool.java:412)
  	at com.zeroc.IceInternal.ThreadPool$EventHandlerThread.run(ThreadPool.java:786)
  	at java.base/java.lang.Thread.run(Thread.java:835)}

)

and vice versa when I stop client on server side I get the same exception.
If we look at line 147 in the TrancieverI.java file, we will see the following code:

            try
            {
                _engine.closeInbound();
            }
            catch(SSLException ex)
            {
                //
                // SSLEngine always raises an exception with this message:
                //
                // Inbound closed before receiving peer's close_notify: possible truncation attack?
                //
                // We would probably need to wait for a response in shutdown() to avoid this.
                // For now, we'll ignore this exception.
                //
                //_instance.logger().error("IceSSL: error during close\n" + ex.getMessage());
            }

In the comments to the SSLEngine.closeInbound() we can read:
"If the application initiated the closing process by calling SSLEngine.closeOutbound(), under some circumstances it is not required that the initiator wait for the peer's corresponding close message. In such cases, this method need not be called." On line 113 of the TrancieverI.java file we find this call (_engine.closeOutbound()).
When I commented out the code above, my server and client began to work without exception.
If you need more detail you can see my project https://github.com/akabanov57/zeroc-ice-osgi
Is this a bug or am I missing something?
Thank you.

@bentoi
Copy link
Member

bentoi commented Sep 17, 2019

You're not missing something. The SSLException exception raised by closeInbound should be caught by the catch(SSLException ex) block and the fact that it is not caught indicates some sort of class loader issue. The exception raised by the SSL layer was most likely loaded with a different class loader.

What is the purpose of the IceRuntimeClassLoader in your client code? Do you have the same issue if you don't set it?

@akabanov57
Copy link
Author

akabanov57 commented Sep 17, 2019 via email

@bentoi
Copy link
Member

bentoi commented Sep 17, 2019

Ok I see, you have to use the OSGi bundle class loader. Note that I don't think you need to check for Ice.Default.Package however... your class loader should just call bundle.loadClass(name) without worrying about the default package.

Regarding the SSLException, you need to figure out why the exception isn't caught. My suggestion would be to change the Ice code to print out the class loader names for the raised exception and for the SSLException class. See the code below. I'm hopping this will give us some clues on the class loaders used for SSLException.

            try
            {
                _engine.closeInbound();
            }
            catch(SSLException ex)
            {
                //
                // SSLEngine always raises an exception with this message:
                //
                // Inbound closed before receiving peer's close_notify: possible truncation attack?
                //
                // We would probably need to wait for a response in shutdown() to avoid this.
                // For now, we'll ignore this exception.
                //
                //_instance.logger().error("IceSSL: error during close\n" + ex.getMessage());
            }
            catch(Exception ex)
            {
                 System.err.println(ex.getClass().getClassLoader().getClass().getName() + ": " + ex.getClass().getClassLoader().toString());
                 System.err.println(SSLException.class.getClassLoader().getClass().getName() + ": " + SSLException.class.getClassLoader().toString());
            }

@akabanov57
Copy link
Author

akabanov57 commented Sep 17, 2019 via email

@pepone
Copy link
Member

pepone commented Sep 17, 2019

I can't ask SSLException.class.getClassLoader(). It will be null.

I'm will be surprised that this doesn't work it will break lot of code, did you actually test it?

@akabanov57
Copy link
Author

akabanov57 commented Sep 17, 2019 via email

@akabanov57
Copy link
Author

akabanov57 commented Sep 17, 2019 via email

@pepone
Copy link
Member

pepone commented Sep 17, 2019

He the root of the problem seems to be that javax.net.ssl.SSLException ends up being loaded from different class loaders, Ice doesn't have any control of how this class is loaded inside the OSGI container. I will expect javax.net.ssl.* will be always load from the system.

Maybe you need to import javax.net.ssl in your bundle MANIFEST?

@akabanov57
Copy link
Author

akabanov57 commented Sep 17, 2019 via email

@akabanov57
Copy link
Author

akabanov57 commented Sep 17, 2019 via email

@pepone
Copy link
Member

pepone commented Sep 17, 2019

shouldn't Private-Package: com.zeroc.IceSSL be just a normal import/export-package? I'm not very familiar with OSGI and it is not clear to me why javax.net.ssl.SSLException is loaded from two different class loaders.

Keep in mind that the class loader set during Ice initilialization will be used by Ice to load plug-ins too, so in this case IceSSL plug-in will be load using your custom class loader.

@akabanov57
Copy link
Author

akabanov57 commented Sep 18, 2019 via email

@bentoi
Copy link
Member

bentoi commented Sep 18, 2019

I haven't been able to reproduce the problem using your test case. I used the latest Eclipse and OpenJDK 12 on macOS. Here's a patch with my project modifications to get things to run: patch.txt. I verified using a breakpoint with the debugger that the exception was caught when I terminate either the client or service.

Did you try to catch the exception in the debugger by adding a catch(Exception) handler in close?

@akabanov57
Copy link
Author

akabanov57 commented Sep 18, 2019 via email

@bentoi
Copy link
Member

bentoi commented Sep 18, 2019

Why are you concerned by the fact that SSL is raising this exception? The SSL debug tracing indeed shows this exception but as far as I can tell it's correctly caught and handled by Ice (it's ignored).

We thought the problem was that the exception wasn't caught by the IceSSL code. After running your test case, following your steps, I can confirm I see the exception in the SSL debug output and that the exception is caught and ignored so it shouldn't be a concern to you.

In any case we'll consider removing this call since it likely fails most of the time and it's not very useful since the socket is closed shortly after.

@akabanov57
Copy link
Author

akabanov57 commented Sep 18, 2019 via email

@akabanov57
Copy link
Author

akabanov57 commented Sep 18, 2019 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants