¿Cómo puedo cerrar con gracia una sesión de Java SSL sin cerrar el socket subyacente?¿Cerrar SSL sin cerrar el socket subyacente?
El caso es que un cliente Java se conecta a un servidor (no Java), configura SSL y envía credenciales de forma segura (nombre de usuario & contraseña) al servidor. El servidor configura un entorno que se ejecuta bajo estas credenciales, genera un nuevo proceso en este entorno y le pasa el manejador de socket, pero la trampa es que este nuevo proceso no puede reutilizar la conexión SSL existente (y no puede usar la sesión SSL) reanudar) ... así que la idea es cerrar SSL antes de que se genere este nuevo proceso, y luego renegociar una sesión SSL desde cero con el nuevo proceso.
El problema es que el método de Java SSLSocket's cierra el socket además de cerrar la sesión SSL (por sending the close_notify alert). No parece haber un equivalente de la función SSL_shutdown() de OpenSSL, que permite dejar abierto el socket subyacente.
He intentado algunas cosas para evitar esto:
Uso SSLSocket.startHandshake() una segunda vez, pero que automáticamente intenta reanudar la sesión SSL en caché existente (que falla, ya que el proceso de servidor generado no lo hace saber de esta sesión), y, si bien hay un método para force resuming SSL sessions or die trying, no hay ningún método para invalidar todas las sesiones en caché o deshabilitar el uso de sesiones en caché.
Creando un
SSLSocket
sobre la parte superior de mi zócalo existente usando SSLSocketFactory.createSocket(), conautoClose
en falso. Esto no impide que el métodoclose()
cierre el socket subyacente, y sospecho que el parámetroautoClose
solo evita que el socket se cierre cuando falla el handshake inicial.Creación de un
SSLSocket
sobre un zócalo existente (como anteriormente), entonces la creación de un segundoSSLSocket
utilizar para el protocolo de enlace SSL con el proceso generado (de un nuevo SSLContext). Esto falla porque cuando el servidor envía la alertaclose_notify
(antes de generar el subproceso), Java cierra el socket.
He oído hablar de SSLEngine, pero también he leído (aunque la fuente actualmente me escapa) que es mucho esfuerzo doloroso para escribir una aplicación correcta de SSL a través de TCP/IP a través de ella, y parece exagerado cuando todo lo que necesito es tener una versión de SSLSocket
cuyo close()
no llame al super.Close()
.
Sin embargo, SSLSocket
no parece que incluso anular close()
(de acuerdo con el javadoc), así que estoy seguro de cómo se engancha el método close()
cuando no parece haber ningún apoyo para el registro de cierre oyentes en Socket
.
La política de la empresa establece que no se pueden usar bibliotecas de cifrado de terceros, por lo que no puedo recurrir a una implementación SSL alternativa como la del Bouncy Castle para resolver el problema.
Si no podemos hacer que funcione el diseño actual de 1 socket, la alternativa es reescribir el servidor & del cliente para usar 2 sockets separados (lo cual es bastante complicado en términos de tener que contrarrestar la denegación de servicio y ataques intermedios, y ¿no se supone que SSL debería ser así en primer lugar?).
Cualquier comentario o idea sobre la forma de resolver este problema sería muy bienvenido.
¿Intentó utilizar un zócalo normal en el fondo? Algo como: 'Socket s = socket nuevo (HOST, PORT); SSLSocket ssl = ...; ssl.connect (s.getRemoteSocketAddress()); ... '? (para mí al menos no cierra el socket "subyacente" ... * probablemente estoy haciendo algo mal * :)) – dacwe
dacwe, tan cerca como puedo decir (ignorando la ... parte de tu fragmento), haciendo ssl.connect() creará una segunda conexión con el host y el socket 's' no se usará en absoluto para las comunicaciones SSL. – Caspar