Unsupported or unrecognized ssl-message exception at startHandshake after issuing STARTTLS command in a java program

本秂侑毒 提交于 2021-02-04 21:54:30

问题


I have written a simple e-mail client in java without using the JavaMail API, as by what I read from the documentation it seems necessary to split the messages up into head and body and in the single MIME-parts for sending which would make my application a lot more complicated. Everything worked fine for a SSL port (465) but now I'm trying to use the client with a different provider that only supports STARTTLS on port 587. The following code is of a class I wrote to test the access to the server.

private static DataOutputStream dos; //Streams to communicate with the server
private static DataInputStream dis;

public static void main(String[] args) {
    try {
        Socket socket = new Socket("mail.arcor.de", 587);
        dos = new DataOutputStream(socket.getOutputStream());
        dis = new DataInputStream(socket.getInputStream());

        new Thread(() -> {readInputRun();}).start(); //see below, every input from the server is printed to the standard output.

        dos.write(("EHLO " + InetAddress.getLocalHost().getHostAddress() + "\r\n").getBytes());

        dos.write("STARTTLS\r\n".getBytes());

        SSLSocket sslSocket = (SSLSocket) ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(socket, "mail.arcor.de", 587, true);
        dos = new DataOutputStream(sslSocket.getOutputStream());
        dis = new DataInputStream(sslSocket.getInputStream());

        sslSocket.startHandshake();

        dos.write(("EHLO " + InetAddress.getLocalHost().getHostAddress() + "\r\n").getBytes());

        dos.write("QUIT\r\n".getBytes());

        Thread.sleep(5000);
        dis.close();
        dos.close();
        socket.close();
    } catch(Exception e) {
        e.printStackTrace();
    }
}

private static void readInputRun() {
    try {
        int input;
        while((input = dis.read()) >= 0) {
            System.out.print((char) input);
        }
    } catch(Exception e) {
        e.printStackTrace();
    }
}

Every time I execute it, I get the following exception:

javax.net.ssl.SSLException: Unsupported or unrecognized SSL message
at java.base/sun.security.ssl.SSLSocketInputRecord.handleUnknownRecord(SSLSocketInputRecord.java:416)
at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:173)
at java.base/sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1031)
at java.base/sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
at java.base/sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1402)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1429)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
at accessTest.AccessTestSTARTTLS.main(AccessTestSTARTTLS.java:31)

It is thrown at line 31, which is 'sslSocket.startHandshake();', so somehow the handshake does not work out. Do I initiate it at the wrong point or in the wrong way?

Thanks in advance for any help.

EDIT: As suggested in the comment, I enabled the logs and found the following: httpslog. In the fifth but last line there is an unreadable character, obviously as part of the client hello, so my computer sends it. Why is this the case and how can I stop that?


回答1:


To be clear, the main intention behind this answer is to mark the question as answered, because actually the solution is found in the comments to the question. The problem lies in the readInputRun() that reads part of the ServerHello, so letting the reading thread interrupt itself before the handshake and restarting it after it solves it:

dos.write("STARTTLS\r\n".getBytes());

SSLSocket sslSocket = (SSLSocket) ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(socket, "mail.arcor.de", 587, true);
dos = new DataOutputStream(sslSocket.getOutputStream());
dis = new DataInputStream(sslSocket.getInputStream());

sslSocket.startHandshake();

new Thread(() -> {readInputRun();}).start();

dos.write(("EHLO " + InetAddress.getLocalHost().getHostAddress() + "\r\n").getBytes());

dos.write("QUIT\r\n".getBytes());

and:

private static void readInputRun() {
    try {
        int input;
        String allInput = "";
        while((input = dis.read()) >= 0) {
            allInput += (char) input;
            System.out.print(allInput.charAt(allInput.length() - 1));

            if(allInput.endsWith("Start TLS\r\n")) {
                break;
            }
        }
    } catch(Exception e) {
        e.printStackTrace();
    }
}


来源:https://stackoverflow.com/questions/48163376/unsupported-or-unrecognized-ssl-message-exception-at-starthandshake-after-issuin

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!