Error with SSL Message

Hello Guys,

I am implementing solution where in I need to post http request to a secure server. I am using following mechanisam to talk to the ssl server. But when I run the program on my local machine I get following error. Can you guys please help me out since I have limited knowledge of security API and I need to get this done in very short time. Please help me understand necessary steps required to resolve this issue.

Thanks

Code

-

SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();

tunnelHost = "<my proxy server >";

tunnelPort = "<proxy server port>";

tunnel = new Socket(tunnelHost, tunnelPort);

doTunnelHandshake(tunnel, host, port ,username , password);

socket =(SSLSocket)factory.createSocket(tunnel, host, port, true);

socket.addHandshakeCompletedListener(

new HandshakeCompletedListener()

{

public void handshakeCompleted(

HandshakeCompletedEvent event)

{"\t CipherSuite:" + event.getCipherSuite());

System.out.println(

"\t SessionId " + event.getSession());

System.out.println(

"\t PeerHost "+

event.getSession().getPeerHost());

}

}

);

socket.startHandshake();

socket.close();

tunnel.close();

} catch (Exception e) {

e.printStackTrace();

}

}

private void doTunnelHandshake(Socket tunnel, String host, int port , String username , String password)

throws IOException

{

OutputStream out = tunnel.getOutputStream();

String AuthString = new String("NORTHAMERICA\\"+username+ ":" + password );

byte [] AuthBytes = AuthString.getBytes();

char []AuthChar = Base64encode(AuthBytes);

String test = String.valueOf(AuthChar);

String ProxyAuthorization = new String("Proxy-Authorization: Basic " + test);

String msg = "CONNECT " + host + ":" + port + " HTTP/1.0\n"

+ "User-Agent: Java SSL Sample\n"

+ "Host: FSM Gateway\n"

+ "Proxy-Connection: Keep-Alive\n"

+ "Pragma: No-Cache\n"

+ ProxyAuthorization

+ "\r\n\r\n";

byte b[];

try {

b = msg.getBytes("ASCII7");

} catch (UnsupportedEncodingException ignored) {

/*

* If ASCII7 isn't there, something serious is wrong, but

* Paranoia Is Good ?br>*/

b = msg.getBytes();

}

out.write(b);

out.flush();

byte reply[] = new byte[200];

int replyLen = 0;

int newlinesSeen = 0;

boolean headerDone = false; /* Done on first newline */

InputStream in = tunnel.getInputStream();

boolean error = false;

while (newlinesSeen < 2) {

int i = in.read();

if (i < 0) {

throw new IOException("Unexpected EOF from proxy");

}

if (i == '\n') {

headerDone = true;

++newlinesSeen;

} else if (i != '\r') {

newlinesSeen = 0;

if (!headerDone && replyLen < reply.length) {

reply[replyLen++] = (byte) i;

}

}

}

/*

* Converting the byte array to a string is slightly wasteful

* in the case where the connection was successful, but it's

* insignificant compared to the network overhead.

*/

String replyStr;

try {

replyStr = new String(reply, 0, replyLen, "ASCII7");

} catch (UnsupportedEncodingException ignored) {

replyStr = new String(reply, 0, replyLen);

}

/* We asked for HTTP/1.0, so we should get that back */

if (!replyStr.startsWith("HTTP/1.0 200")) {

throw new IOException("Unable to tunnel through "

+ tunnelHost + ":" + tunnelPort

+ ". Proxy returns \"" + replyStr + "\"");

}

System.out.println("tunneling Handshake was successful!");

}

Exception is javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?

at com.sun.net.ssl.internal.ssl.InputRecord.b(Unknown Source)

at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.j(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)

at SSLSocketClient.doIt(SSLSocketClient.java:166)

at SSLSocketClient.main(SSLSocketClient.java:54)

--

Debug information is

keyStore is :

keyStore type is : jks

init keystore

init keymanager of type SunX509

trustStore is: C:\Program Files\Java\j2re1.4.2_06\lib\security\cacerts

trustStore type is : jks

init truststore

adding as trusted cert:

Subject: CN=Baltimore CyberTrust Code Signing Root, OU=CyberTrust, O=Baltimore, C=IE

Issuer: CN=Baltimore CyberTrust Code Signing Root, OU=CyberTrust, O=Baltimore, C=IE

Algorithm: RSA; Serial number: 0x20000bf

Valid from Wed May 17 09:01:00 CDT 2000 until Sat May 17 18:59:00 CDT 2025

adding as trusted cert:

Subject: CN=Entrust.net Secure Server Certification Authority, OU=(c) 1999 Entrust.net Limited, OU=www.entrust.net/CPS incorp. by ref. (limits liab.),

Issuer: CN=Entrust.net Secure Server Certification Authority, OU=(c) 1999 Entrust.net Limited, OU=www.entrust.net/CPS incorp. by ref. (limits liab.),

Algorithm: RSA; Serial number: 0x374ad243

Valid from Tue May 25 11:09:40 CDT 1999 until Sat May 25 11:39:40 CDT 2019

adding as trusted cert:

Subject: CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE

Issuer: CN=Baltimore CyberTrust Root, OU=CyberTrust, O=Baltimore, C=IE

Algorithm: RSA; Serial number: 0x20000b9

Valid from Fri May 12 13:46:00 CDT 2000 until Mon May 12 18:59:00 CDT 2025

adding as trusted cert:

Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3, OU="(c) 1999 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Net

Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3, OU="(c) 1999 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Net

Algorithm: RSA; Serial number: 0x9b7e0649a33e62b9d5ee90487129ef57

Valid from Thu Sep 30 19:00:00 CDT 1999 until Wed Jul 16 18:59:59 CDT 2036

adding as trusted cert:

init context

trigger seeding of SecureRandom

done seeding SecureRandom

tunneling Handshake was successful!

Socket is 15e83f9[SSL_NULL_WITH_NULL_NULL: Socket[addr=/10.0.1.38,port=80,localport=2133]]

%% No cached client session

*** ClientHello, TLSv1

RandomCookie: GMT: 1115833203 bytes = { 119, 0, 234, 70, 240, 74, 55, 9, 64, 89, 133, 251, 64, 160, 105, 25, 113, 219, 252, 65, 240, 228, 184, 117, 235,

Session ID: {}

Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_

Compression Methods: { 0 }

***

main, WRITE: TLSv1 Handshake, length = 73

main, WRITE: SSLv2 client hello message, length = 98

main, handling exception: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?

main, SEND TLSv1 ALERT: fatal, description = unexpected_message

main, WRITE: TLSv1 Alert, length = 2

main, called closeSocket()

javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?

at com.sun.net.ssl.internal.ssl.InputRecord.b(Unknown Source)

at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.j(Unknown Source)

at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)

at SSLSocketClient.doIt(SSLSocketClient.java:166)

at SSLSocketClient.main(SSLSocketClient.java:54)

[7918 byte] By [developer_atga] at [2007-10-2 5:47:32]
# 1
I would say you aren't consuming the entire reply to the CONNECT string so the SSLSocket is trying and failing to decrypt part of it.Also you should be sending \r\n not just \n with the CONNECT request.
ejpa at 2007-7-16 1:57:08 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 2

Are you sure your final target is accepting ssl/tls and not raw connections? the debug suggests the SSL socket been aimed at addr=/10.0.1.38,port=80 which should make you concerned if that is the proper port for the ssl server.

I might oversee something but i think the code is still compliant to the orignal version on apache soap SSLUtils, which you actually could use directly for your application though.

babakNa at 2007-7-16 1:57:08 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 3

I think I might know what is the problem, I just overlooked it. My remote host is something like this https://abc.com/xyz and port is 443.

So when I say socket =

(SSLSocket)factory.createSocket(tunnel, host, port, true); I guess it is connecting as https://abc.com/xyz:443 instead of https://abc.com:443/xyz

am I correct ?

If this is correct any idea how to get around this.

Thanks

developer_atga at 2007-7-16 1:57:08 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...
# 4

No it is not correct.

The socket creation should be provided with the proper host and the port. the resource on the host is something you should ask your server (HTTP GET ... whatever).

The https://abc.com:443 is equal to https://abc.com as the default port for https is 443. the host variable should be "abc.com" and the port "443" and the rest negotiated in application level (HTTP GET /XYZ [is not the proper syntax]).

Further, with this description, the first url (https://server/resource:port) is not making any sense.

You problem in first place is probably the host and port parameters (specifically the port has been set to 80 which most likely is wrong) . you need to consider the other port regarding newline and CRs buildging the proxy authentication header, but you debug logs suggest that your test proxy server takes it.

babakNa at 2007-7-16 1:57:08 > top of Java-index,Security,Java Secure Socket Extension (JSSE)...