5 Replies Latest reply on Aug 15, 2006 12:30 PM by mazz

    Encryption in Remoting

    anil.saldhana

      Related to http://jira.jboss.com/jira/browse/JBREM-419

      I plug in a CipherOutputStream to the JBossObjectOutputStream. The issue with COS is that it needs an explicit close() to flush all the data across. But this causes a socket write error as shown:

       [SocketServerInvokerThread-127.0.0.1-0] ERROR org.jboss.remoting.transport.socket.ServerThread - failed to process invocation.
      java.net.SocketException: Software caused connection abort: socket write error
       at java.net.SocketOutputStream.socketWrite0(Native Method)
       at java.net.SocketOutputStream.socketWrite(Unknown Source)
       at java.net.SocketOutputStream.write(Unknown Source)
       at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
       at java.io.BufferedOutputStream.flush(Unknown Source)
       at java.io.DataOutputStream.flush(Unknown Source)
       at org.jboss.serial.io.JBossObjectOutputStream.flush(JBossObjectOutputStream.java:248)
       at javax.crypto.CipherOutputStream.flush(DashoA12275)
       at java.io.DataOutputStream.flush(Unknown Source)
       at org.jboss.serial.io.JBossObjectOutputStream.flush(JBossObjectOutputStream.java:248)
       at org.jboss.remoting.serialization.impl.jboss.JBossSerializationManager.sendObject(JBossSerializationManager.java:95)
       at org.jboss.remoting.marshal.serializable.SerializableMarshaller.write(SerializableMarshaller.java:84)
       at org.jboss.remoting.marshal.encryption.EncryptingMarshaller.write(EncryptingMarshaller.java:123)
       at org.jboss.remoting.transport.socket.ServerThread.versionedWrite(ServerThread.java:484)
       at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:463)
      


      Clebert mentioned that there may be an issue with JBossOOS close with the following:
      public void close() throws IOException {
       flush();
       dataOutput.close();
       dataOutput.close();
       }
      


      A copy/paste error.

      * I do not know yet whether the socket write error is something related to JBossOOS close or the other side closed the socket.


      EncryptingMarshaller code:

      public void write(Object dataObject, OutputStream output) throws IOException
       {
       if(cipher == null)
       throw new IllegalStateException("Cipher is null for algo="+ this.cipherAlgorithm);
       output.flush();
      
       CipherOutputStream cos = new CipherOutputStream(output, cipher);
      
       SerializationManager sm = SerializationStreamFactory.getManagerInstance(getSerializationType());
       ObjectOutputStream oos = sm.createOutput(cos);
      
       if(wrappedMarshaller != null)
       {
       wrappedMarshaller.write(dataObject, oos);
       }
       else
       {
       super.write(dataObject, oos);
       }
       oos.flush();
       cos.close();
       oos.close(); //There is a need to close cos
       }
      


      Clebert fixed the following:
      http://jira.jboss.com/jira/browse/JBSER-87

        • 1. Re: Encryption in Remoting
          anil.saldhana

          If I remove the explicit cos.close()

          So I now get:

          2006-08-15 10:27:25,619 ERROR [org.jboss.remoting.transport.socket.ServerThread] failed to process invocation.
          java.net.SocketException: Socket closed
           at java.net.SocketOutputStream.socketWrite(Unknown Source)
           at java.net.SocketOutputStream.write(Unknown Source)
           at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
           at java.io.BufferedOutputStream.flush(Unknown Source)
           at java.io.DataOutputStream.flush(Unknown Source)
           at org.jboss.serial.io.JBossObjectOutputStream.flush(JBossObjectOutputStream.java:248)
           at org.jboss.serial.io.JBossObjectOutputStream.close(JBossObjectOutputStream.java:261)
           at javax.crypto.CipherOutputStream.close(DashoA12275)
           at java.io.FilterOutputStream.close(Unknown Source)
           at org.jboss.serial.io.JBossObjectOutputStream.close(JBossObjectOutputStream.java:263)
           at org.jboss.remoting.marshal.encryption.EncryptingMarshaller.write(EncryptingMarshaller.java:127)
           at org.jboss.remoting.transport.socket.ServerThread.versionedWrite(ServerThread.java:484)
           at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:463)
          


          Maybe the other side has closed the stream or a socket timeout?

          • 2. Re: Encryption in Remoting
            clebert.suconic

            I just think you shouldn't be calling .close in your streamings at all:

            Can't you just do:


            public void write(Object dataObject, OutputStream output) throws IOException
             {
             if(cipher == null)
             throw new IllegalStateException("Cipher is null for algo="+ this.cipherAlgorithm);
             output.flush();
            
             CipherOutputStream cos = new CipherOutputStream(output, cipher);
            
             SerializationManager sm = SerializationStreamFactory.getManagerInstance(getSerializationType()
            );
             ObjectOutputStream oos = sm.createOutput(cos);
            
             if(wrappedMarshaller != null)
             {
             wrappedMarshaller.write(dataObject, oos);
             }
             else
             {
             super.write(dataObject, oos);
             }
             oos.flush();
             // cos.close(); pp remove this and let GC take care of these instances
             // oos.close(); //There is a need to close cos
             }
            


            Take a look on the other marshallers... they always keep the streaming opened and only use flush();



            • 3. Re: Encryption in Remoting
              anil.saldhana

              That is the problem with CipherOutputStream. Unless you close(), data is not flushed across due to buffers waiting for data to be filled.

              Maybe we should revisit encryption in remoting like the way Scott implemented earlier - a CipherSocket based on Password based encryption.

              • 4. Re: Encryption in Remoting
                clebert.suconic

                If you can't find a parameter to flush data without close the stream...

                What about to use a fake output stream to change the behavior on .close operations:

                It's kind of a hack... but if there isn't another option.

                import java.io.IOException;
                import java.io.*;
                
                public class FlushOnCloseOutputStream extends OutputStream
                {
                 OutputStream delegate;
                
                 public void close() throws IOException {
                 delegate.flush(); // here
                 }
                
                 public boolean equals(Object arg0) {
                 return delegate.equals(arg0);
                 }
                
                 public void flush() throws IOException {
                 delegate.flush();
                 }
                
                 public int hashCode() {
                 return delegate.hashCode();
                 }
                
                 public void write(byte[] b, int off, int len) throws IOException {
                 delegate.write(b, off, len);
                 }
                
                 public void write(byte[] b) throws IOException {
                 delegate.write(b);
                 }
                
                 public void write(int b) throws IOException {
                 delegate.write(b);
                 }
                
                }
                


                • 5. Re: Encryption in Remoting
                  mazz

                  What's the use-case? Do you just want encryption without the need for certificates? If so, Remoting has this capability now - you can use SSL transports (https, sslsocket) and configure it so you don't need certs on either end (i.e. just use SSL for encryption without authentication).