I've been trying to implement a HTTPS/SSL server in Java, and I've tried using a number of different code examples, but they all seem to fail at the point that the server has read the request. Below is one example I've been working with, and when I run that with Firefox, I get this error:
[write] MD5 and SHA1 hashes: len = 16
0000: 14 00 00 0C 73 A7 11 73 AE 3C 41 C5 91 C7 E9 19 ....s..s.<A.....
Padded plaintext before ENCRYPTION: len = 16
0000: 14 00 00 0C 73 A7 11 73 AE 3C 41 C5 91 C7 E9 19 ....s..s.<A.....
main, WRITE: TLSv1.2 Handshake, length = 40
main, waiting for close_notify or alert: state 1
main, Exception while waiting for close java.net.SocketException: Software caused connection abort: recv failed
main, handling exception: java.net.SocketException: Software caused connection abort: recv failed
%% Invalidated: [Session-1, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
Priv exp --- null
Exception occurred .... java.net.SocketException: Software caused connection abort: recv failed
java.net.SocketException: Software caused connection abort: recv failed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at sun.security.ssl.InputRecord.readFully(Unknown Source)
at sun.security.ssl.InputRecord.read(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.waitForClose(Unknown Source)
at sun.security.ssl.HandshakeOutStream.flush(Unknown Source)
at sun.security.ssl.Handshaker.sendChangeCipherSpec(Unknown Source)
at sun.security.ssl.ServerHandshaker.sendChangeCipherAndFinish(Unknown Source)
at sun.security.ssl.ServerHandshaker.clientFinished(Unknown Source)
at sun.security.ssl.ServerHandshaker.processMessage(Unknown Source)
at sun.security.ssl.Handshaker.processLoop(Unknown Source)
at sun.security.ssl.Handshaker.process_record(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.readDataRecord(Unknown Source)
at sun.security.ssl.AppInputStream.read(Unknown Source)
at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
at sun.nio.cs.StreamDecoder.read(Unknown Source)
at java.io.InputStreamReader.read(Unknown Source)
at java.io.BufferedReader.fill(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at java.io.BufferedReader.readLine(Unknown Source)
at SSLServer.main(SSLServer.java:65)
and, here's the code:
import java.io.*;
import java.security.Security;
import java.security.PrivilegedActionException;
import javax.net.ssl.*;
import com.sun.net.ssl.*;
import com.sun.net.ssl.internal.ssl.Provider;
/**
* #author Joe Prasanna Kumar
* This program simulates an SSL Server listening on a specific port for client requests
*
* Algorithm:
* 1. Regsiter the JSSE provider
* 2. Set System property for keystore by specifying the keystore which contains the server certificate
* 3. Set System property for the password of the keystore which contains the server certificate
* 4. Create an instance of SSLServerSocketFactory
* 5. Create an instance of SSLServerSocket by specifying the port to which the SSL Server socket needs to bind with
* 6. Initialize an object of SSLSocket
* 7. Create InputStream object to read data sent by clients
* 8. Create an OutputStream object to write data back to clients.
*
*/
public class SSLServer {
/**
* #param args
*/
public static void main(String[] args) throws Exception{
int intSSLport = 4443; // Port where the SSL Server needs to listen for new requests from the client
{
// Registering the JSSE provider
Security.addProvider(new Provider());
//Specifying the Keystore details
System.setProperty("javax.net.ssl.keyStore","C:\\Users\\test\\Eclipse-workspaces\\Test\\newkeystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword","changeit");
// Enable debugging to view the handshake and communication which happens between the SSLClient and the SSLServer
System.setProperty("javax.net.debug","all");
}
try {
// Initialize the Server Socket
SSLServerSocketFactory sslServerSocketfactory = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket = (SSLServerSocket)sslServerSocketfactory.createServerSocket(intSSLport);
SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept();
// Create Input / Output Streams for communication with the client
while(true)
{
PrintWriter out = new PrintWriter(sslSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
sslSocket.getInputStream()));
String inputLine, outputLine;
System.out.println("Start reading socket");
while ((inputLine = in.readLine()) != null) {
//out.println(inputLine);
System.out.println(inputLine);
}
System.out.println("Finished reading socket");
// Send the response
// Send the headers
out.println("HTTP/1.0 200 OK");
out.println("Content-Type: text/html");
out.println("Server: Bot");
// this blank line signals the end of the headers
out.println("");
// Send the HTML page
out.println("<H1>Welcome to the Ultra Mini-WebServer</H2>");
out.flush();
// Close the streams and the socket
out.close();
in.close();
sslSocket.close();
sslServerSocket.close();
}
}
catch(Exception exp)
{
PrivilegedActionException priexp = new PrivilegedActionException(exp);
System.out.println(" Priv exp --- " + priexp.getMessage());
System.out.println(" Exception occurred .... " +exp);
exp.printStackTrace();
}
}
}
As I said, I've tried a bunch of other example programs that are similar, and they all seem to fail at the same area, after the read of the request.
NOTE that if I use openssl s_client and type the same input request in manually it works.
Can anyone help point me to what might be wrong?
Thanks,
Jim
EDIT:
I think that I've made some progress, with a different example server code, the one from here:
http://www.herongyang.com/JDK/HTTPS-Server-Test-Program-HttpsHello.html
First of all, again, if I run this app and hit it from "openssl s_client", it works fine when I manually enter a "GET".
But, if I try using Firefox, as soon as I send a request to https://192.168.0.6:8888 (FYI, doesn't matter if I use a hostname that matches cert), I get a popup asking me to add an exception and ALSO, I get at the app/server end:
Server started:
Server socket class: class sun.security.ssl.SSLServerSocketImpl
Socket address = 0.0.0.0/0.0.0.0
Socket port = 8888
Need client authentication = false
Want client authentication = false
Use client mode = false
Socket class: class sun.security.ssl.SSLSocketImpl
Remote address = /192.168.0.5
Remote port = 58972
Local socket address = /192.168.0.5:8888
Local address = /192.168.0.5
Local port = 8888
Need client authentication = false
Cipher suite = SSL_NULL_WITH_NULL_NULL
Protocol = NONE
Read=[null]
java.net.SocketException: Connection closed by remote host
at sun.security.ssl.SSLSocketImpl.checkWrite(Unknown Source)
at sun.security.ssl.AppOutputStream.write(Unknown Source)
at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)
at sun.nio.cs.StreamEncoder.flush(Unknown Source)
at java.io.OutputStreamWriter.flush(Unknown Source)
at java.io.BufferedWriter.flush(Unknown Source)
at HttpsHello.main(HttpsHello.java:43)
So, I did something differently.
I started Firefox, then went to Options->Advanced->Certificates->Add Exception
For the exception, I put the URL to get the cert, https://192.168.0.5:8888
The app blew up as soon as I clicked "Get Certificate":
Server started:
Server socket class: class sun.security.ssl.SSLServerSocketImpl
Socket address = 0.0.0.0/0.0.0.0
Socket port = 8888
Need client authentication = false
Want client authentication = false
Use client mode = false
Socket class: class sun.security.ssl.SSLSocketImpl
Remote address = /192.168.0.5
Remote port = 59018
Local socket address = /192.168.0.5:8888
Local address = /192.168.0.5
Local port = 8888
Need client authentication = false
Cipher suite = SSL_NULL_WITH_NULL_NULL
Protocol = NONE
Read=[null]
java.net.SocketException: Connection closed by remote host
at sun.security.ssl.SSLSocketImpl.checkWrite(Unknown Source)
at sun.security.ssl.AppOutputStream.write(Unknown Source)
at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)
at sun.nio.cs.StreamEncoder.flush(Unknown Source)
at java.io.OutputStreamWriter.flush(Unknown Source)
at java.io.BufferedWriter.flush(Unknown Source)
at HttpsHello.main(HttpsHello.java:43)
BUT, Firefox let me add a temporary exception at this point!!
Ok, then after adding the temporary exception, I restarted the app, and put in https://192.168.0.5:8888 into the Firefox address, and, at that point, IT WORKED, i.e., I got the "Hello world" web page in Firefox!!
Does anyone know why this is happening? Why is it that "openssl s_client" works, but it blows up with Firefox, APPARENTLY when Firefox is getting the cert from the app to add the cert as an exception?
EDIT 2:
I posted in comments that I got this working on one of my laptops, but I still haven't gotten it working on my main development machine.
I am pasting in the SSL debug log from a test I just did at:
http://pastebin.com/faVCjj3a
If anyone can see anything that might be causing this please let me know? I did this test after moving over the exact JKS file and certs from the working system. Also, I've installed the unlimited strength policy jars on this other system.
Thanks...
EDIT 3: I think I've finally found an example that seems to work:
http://www.mybinarylife.net/2012/06/java-ssl-threaded-echo-server.html
I modified that code slightly to send HTTP response instead of just echoing the request, and it seems to work even with a browser like Firefox.
It appears that the difference between hitting the server with openssl s_client and a browser is that when the first request is made, and the browser finds some problem like the hostname not matching the cert or other situations, and when the browser like Firefox is asking for an exception, there is an SSL error, so the server has to be able to handle that and continue handling the request/connection, rather than just dying, which this new example seems to do.
Related
I have run into an issue developing a HTTP client with the use of BouncyCastle libraries.
Target versions (but the error is also reproducible in Java 1.8.0_91 with the same version of BouncyCastle.)
JRE 1.6.0_45-b06
BouncyCastle jdk15to18 167 (bcprov-jdk15to18-167.jar, bcpkix-jdk15to18-167.jar, bctls-jdk15to18-167.jar)
HTTPClient code:
String strURL = "https://www.<WEBSITE>.com";
// CODE to set default TrustStore, KeyStore to be used
// setup BC as SecurityProvider and SSLSocketFactoryProvider
/*
Security.insertProviderAt(new BouncyCastleProvider(), 1);
Security.insertProviderAt(new BouncyCastleJsseProvider(), 2);
Security.setProperty("ssl.KeyManagerFactory.algorithm", "PKIX");
Security.setProperty("ssl.TrustManagerFactory.algorithm", "PKIX");
Security.setProperty("ssl.SocketFactory.provider", "org.bouncycastle.jsse.provider.SSLSocketFactoryImpl");
System.setProperty("jdk.tls.trustNameService", "true");
*/
URL url = new URL( strURL );
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("GET");
InputStream is = null;
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
System.out.println("OK");
is = conn.getInputStream();
} else if (conn.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) {
System.out.println("ERROR");
is = conn.getErrorStream();
} else {
System.out.println( conn.getResponseCode() );
System.out.println( conn.getResponseMessage() );
}
if (is != null) {
System.out.println( readFullyAsString(is, "UTF-8") );
}
conn.disconnect();
Accessing data on a website with TLS 1.2 without client_auth works fine (there are some issues with specific sites that return handshake_failure(40), but luckily not in our case). But when client_auth is required the code fails with the following (a little cryptic) error:
nov. 27, 2020 5:23:10 PM org.bouncycastle.jsse.provider.ProvTlsClient notifyAlertRaised
WARNING: Client raised fatal(2) internal_error(80) alert: Failed to read record
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at org.bouncycastle.tls.RecordStream$Record.fillTo(RecordStream.java:429)
at org.bouncycastle.tls.RecordStream$Record.readHeader(RecordStream.java:468)
at org.bouncycastle.tls.RecordStream.readRecord(RecordStream.java:201)
at org.bouncycastle.tls.TlsProtocol.safeReadRecord(TlsProtocol.java:768)
at org.bouncycastle.tls.TlsProtocol.readApplicationData(TlsProtocol.java:731)
at org.bouncycastle.jsse.provider.ProvSSLSocketDirect$AppDataInput.read(ProvSSLSocketDirect.java:603)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read1(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.HttpURLConnection.getResponseCode(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
at HttpsClient.main(HttpsClient.java:109)
nov. 27, 2020 5:23:10 PM org.bouncycastle.jsse.provider.ProvTlsClient notifyAlertRaised
WARNING: Client raised fatal(2) internal_error(80) alert: Failed to read record
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at org.bouncycastle.tls.RecordStream$Record.fillTo(RecordStream.java:429)
at org.bouncycastle.tls.RecordStream$Record.readHeader(RecordStream.java:468)
at org.bouncycastle.tls.RecordStream.readRecord(RecordStream.java:201)
at org.bouncycastle.tls.TlsProtocol.safeReadRecord(TlsProtocol.java:768)
at org.bouncycastle.tls.TlsProtocol.readApplicationData(TlsProtocol.java:731)
at org.bouncycastle.jsse.provider.ProvSSLSocketDirect$AppDataInput.read(ProvSSLSocketDirect.java:603)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read1(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.HttpURLConnection.getResponseCode(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
at HttpsClient.main(HttpsClient.java:109)
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at org.bouncycastle.tls.RecordStream$Record.fillTo(RecordStream.java:429)
at org.bouncycastle.tls.RecordStream$Record.readHeader(RecordStream.java:468)
at org.bouncycastle.tls.RecordStream.readRecord(RecordStream.java:201)
at org.bouncycastle.tls.TlsProtocol.safeReadRecord(TlsProtocol.java:768)
at org.bouncycastle.tls.TlsProtocol.readApplicationData(TlsProtocol.java:731)
at org.bouncycastle.jsse.provider.ProvSSLSocketDirect$AppDataInput.read(ProvSSLSocketDirect.java:603)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read1(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at java.net.HttpURLConnection.getResponseCode(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(Unknown Source)
at HttpsClient.main(HttpsClient.java:109)
As expected the code runs just fine in Java 1.8 without BC as Security Provider ... but in Java 1.6 BC is needed for TLS 1.2 support.
I looked at the packets with Wireshark, but I don't have enough knowledge to analyze what's happening (failing) with the SSL handshake operation with the server.
What am I missing here? Or it's just a known limitation of BC?
Thanks for any suggestions.
After extensive research and testing (we set up our own dev environment that replicated the endpoint, we were trying to connect to with client cert) we have found a solution (posted below) that works for us in our dev environment, but couldn't be configured on the endpoint. That's why we went to plan B - TLS termination proxy and it worked like a charm in our case, when we didn't have control of the server environment.
Solution for IIS
In our case the web service requiring client auth was running on Microsoft IIS. As stated "Unfortunately our TLS libraries do not support renegotiation (and we do not plan to add it, although there are corresponding TLS 1.3 features that we will)." in this open issue (https://github.com/bcgit/bc-java/issues/593). After reading the IIS documentation and some testing we successfully configured the environment in a way that TLS sessions could be established with BC TLS lib:
Step 1:
Create an IIS site with default settings
Run IISCrypto with the "Best practices" template:
Step 2:
Enable SSLAlwaysNegoClientCert
Save the following text to a file called "Enable_SSL_Renegotiate.js"
var vdirObj=GetObject("IIS://localhost/W3svc/1");
// replace 1 on this line with the number of the web site you wish to configure
WScript.Echo("Value of SSLAlwaysNegoClientCert Before: " + vdirObj.SSLAlwaysNegoClientCert);
vdirObj.Put("SSLAlwaysNegoClientCert", true);
vdirObj.SetInfo();
WScript.Echo("Value of SSLAlwaysNegoClientCert After: " + vdirObj.SSLAlwaysNegoClientCert);
Run the following command from an elevated / administrator command prompt:
cscript.exe enable_ssl_renegotiate.js
I posted the same answer on BouncyCastle Github - #847
I'm trying to connect to an Oracle DB using Java and SSL. For now I have the Java program on the server with the database.
I'm getting this error when I try to run it (full error in comment):
java.sql.SQLRecoverableException: IO Error: Inbound closed before receiving peer's close_notify: possible truncation attack?, connect lapse 15 ms., Authentication lapse 0 ms.
This is my java code:
public static void main(String[] args) {
Security.addProvider(new oracle.security.pki.OraclePKIProvider());
String url = "jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=localhost)(PORT=2484))(CONNECT_DATA=(SERVICE_NAME=ORCL)))";
Properties props = new Properties();
props.setProperty("javax.net.ssl.trustStore",
"C:\\app\\Administrator\\virtual\\product\\12.2.0\\dbhome_1\\bin\\wallets\\Administrator\\cwallet.sso");
props.setProperty("javax.net.ssl.trustStoreType","SSO");
props.setProperty("javax.net.ssl.keyStore",
"C:\\app\\Administrator\\virtual\\product\\12.2.0\\dbhome_1\\bin\\wallets\\Administrator\\cwallet.sso");
props.setProperty("javax.net.ssl.keyStoreType","SSO");
try {
Connection conn = DriverManager.getConnection(url, props);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I added this to listener.ora and tnsnames.ora (I also tried with the sso file and just linking to the directory)
WALLET_LOCATION=(SOURCE=(METHOD=FILE) (METHOD_DATA=(DIRECTORY=C:\app\Administrator\virtual\product\12.2.0\dbhome_1\bin\wallets\Administrator\ewallet.p12 ))
SSL_CLIENT_AUTHENTICATION=TRUE
I also added this to java.security:
security.provider.11=oracle.security.pki.OraclePKIProvider
edit: I didn't realize the length limit on comments was so short. Here's the full error:
Caused by: java.io.IOException: Inbound closed before receiving peer's close_notify: possible truncation attack?, connect lapse 11 ms., Authentication lapse 0 ms.
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:790)
... 6 more
Caused by: java.io.IOException: Inbound closed before receiving peer's close_notify: possible truncation attack?, connect lapse 11 ms.
at oracle.net.ns.NSProtocolNIO.negotiateConnection(NSProtocolNIO.java:138)
at oracle.net.ns.NSProtocol.connect(NSProtocol.java:317)
at oracle.jdbc.driver.T4CConnection.connect(T4CConnection.java:1438)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:518)
... 6 more
Caused by: javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?
at sun.security.ssl.Alerts.getSSLException(Unknown Source)
at sun.security.ssl.SSLEngineImpl.fatal(Unknown Source)
at sun.security.ssl.SSLEngineImpl.fatal(Unknown Source)
at sun.security.ssl.SSLEngineImpl.closeInbound(Unknown Source)
at oracle.net.nt.SSLSocketChannel.fill(SSLSocketChannel.java:534)
at oracle.net.nt.SSLSocketChannel.unwrap(SSLSocketChannel.java:434)
at oracle.net.nt.SSLSocketChannel.handshake(SSLSocketChannel.java:350)
at oracle.net.nt.SSLSocketChannel.write(SSLSocketChannel.java:238)
at oracle.net.ns.NIOPacket.writeToSocketChannel(NIOPacket.java:211)
at oracle.net.ns.NIOConnectPacket.writeToSocketChannel(NIOConnectPacket.java:232)
at oracle.net.ns.NSProtocolNIO.negotiateConnection(NSProtocolNIO.java:108)
... 9 more
Can you make sure to have oraclepki.jar, osdt_core.jar and osdt_cert.jar in the classpath? You don't need to use keystore and truststore properties. Use oracle.net.wallet_location and oracle.net.ssl_server_dn_match=true. Check out the blog for more details.
i try to send mail using aspose but the build for program is runing for along time then give me errorthis is my code
public static void main(String[] args) {
SmtpClient client = new SmtpClient("smtp.gmail.com", 587, "kerolos", "MyPassword");
MailMessage message = new MailMessage();
message.setFrom(new MailAddress("sender#gmail.com"));
message.getTo().addMailAddress(new MailAddress("reciver#gmail.com"));
message.setBody("nothinge");
message.setSubject("me");
client.send(message);
}
for sure i downloaded and import all libarar that i need
this is my error
Exception in thread "main" class com.aspose.email.SmtpException: Failure sending mail. ---> class com.aspose.email.SmtpException: The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required. Learn more at
5.5.1 https://support.google.com/mail/?p=WantAuthError g73sm13415755wme.16 - gsmtp
com.aspose.email.abk.f(SourceFile:49)
com.aspose.email.asu.n(SourceFile:130)
com.aspose.email.cg.a(SourceFile:311)
com.aspose.email.internal.ah.h.a(Unknown Source)
com.aspose.email.internal.ah.j.run(Unknown Source)
java.lang.Thread.run(Thread.java:745)
--- End of inner exception stack trace ---
com.aspose.email.SmtpClient.a(SourceFile:1982)
com.aspose.email.SmtpClient.send(SourceFile:1785)
test.mina.main(mina.java:23)
at com.aspose.email.SmtpClient.a(SourceFile:1982)
at com.aspose.email.SmtpClient.send(SourceFile:1785)
at test.mina.main(mina.java:23)
Caused by: class com.aspose.email.SmtpException: The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required. Learn more at
5.5.1 https://support.google.com/mail/?p=WantAuthError g73sm13415755wme.16 - gsmtp
com.aspose.email.abk.f(SourceFile:49)
com.aspose.email.asu.n(SourceFile:130)
com.aspose.email.cg.a(SourceFile:311)
com.aspose.email.internal.ah.h.a(Unknown Source)
com.aspose.email.internal.ah.j.run(Unknown Source)
java.lang.Thread.run(Thread.java:745)
at com.aspose.email.abk.f(SourceFile:49)
at com.aspose.email.asu.n(SourceFile:130)
at com.aspose.email.cg.a(SourceFile:311)
at com.aspose.email.internal.ah.h.a(Unknown Source)
at com.aspose.email.internal.ah.j.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Java returned: 1
BUILD FAILED (total time: 35 seconds)
GMail has strict rules for accessing emails by less secure applications. In order to allow GMail account to be accessed by less secure applications, you should enable the access by configuring your email account.
https://support.google.com/a/answer/6260879?hl=en
Please try it at your end and if the issue still persists, you can write to us on Aspose.Email forum for further assistance.
I work with Aspose as Developer Evangelist.
I have the following code:
package daoImp;
import java.util.List;
import javapns.Push;
import javapns.communication.exceptions.KeystoreException;
import javapns.notification.PushedNotification;
import javapns.notification.ResponsePacket;
import org.json.JSONException;
import com.sun.jmx.snmp.daemon.CommunicationException;
public class Notification {
public static void main(String args[]) {
try {
new Notification().sendMessageToAPN();
} catch (CommunicationException | KeystoreException | JSONException
| javapns.communication.exceptions.CommunicationException e) {
e.printStackTrace();
}
}
public void sendMessageToAPN() throws CommunicationException,
KeystoreException, JSONException,
javapns.communication.exceptions.CommunicationException {
String regId1 = "6f9d340ab4d0f81206f7d8c1ab7b8994d90d139e0d1d2b99999b02887e60d54f";
List<PushedNotification> notifications = Push.alert("hello","C:/Program Files (x86)/Java/jdk1.7.0_21/jre/lib/security/gameover.p12", "gameover",
false, regId1);
for (PushedNotification notification : notifications) {
if (notification.isSuccessful()) {
System.out.println("Push notification sent successfully to: " + notification.getDevice().getToken());
} else {
String invalidToken = notification.getDevice().getToken();
System.err.println("Invalid Token " + invalidToken);
System.out.println(" The problem was");
Exception theProblem = notification.getException();
theProblem.printStackTrace();
ResponsePacket theErrorResponse = notification.getResponse();
if (theErrorResponse != null) {
System.out.println(theErrorResponse.getMessage());
}
}
}
}
}
When I run the code, I get the following exception message: handshake to ssl failed as connection to remote host failed during handshake.
log4j:WARN No appenders could be found for logger (javapns.notification.Payload).
log4j:WARN Please initialize the log4j system properly.
Invalid Token 6f9d340ab4d0f81206f7d8c1ab7b6774d90d139e0d1d2b58599b02887e60d54f
The problem was
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at sun.security.ssl.SSLSocketImpl.writeRecord(Unknown Source)
at sun.security.ssl.AppOutputStream.write(Unknown Source)
at java.io.OutputStream.write(Unknown Source)
at javapns.notification.PushNotificationManager.sendNotification(PushNotificationManager.java:402)
at javapns.notification.PushNotificationManager.sendNotification(PushNotificationManager.java:350)
at javapns.notification.PushNotificationManager.sendNotification(PushNotificationManager.java:320)
at javapns.Push.sendPayload(Push.java:177)
at javapns.Push.alert(Push.java:47)
at daoImp.Notification.sendMessageToAPN(Notification.java:27)
at daoImp.Notification.main(Notification.java:16)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(Unknown Source)
... 12 more
I don't know why I'm getting this message.
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
Caused by: java.io.EOFException: SSL peer shut down incorrectly
Above Exception is a generic exception we get in the client if there is any of below scenario:
If Server and Client support different version of TLS e.g. server
support TLS2 while Client support only TLS1. This issue can be resolved by setting below property in Client side :
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
If the server is not able to validate the certificate chain of the client, then also it will close the conection.
Certificate chain qtp510727907-31, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain %%
Invalidated: [Session-3, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA]
qtp510727907-31, SEND TLSv1 ALERT: fatal, description =
bad_certificate qtp510727907-31, WRITE: TLSv1 Alert, length = 2
main, WRITE: TLSv1 Change Cipher Spec, length = 1 qtp510727907-31,
fatal: engine already closed. Rethrowing
javax.net.ssl.SSLHandshakeException: null cert chain
To know the exact cause of failure, we need to enable -Djavax.net.debug=all while executing the client call towards the server.
This issue occurs because of Internet connection problem/poor internet connection.
Please check your internet connectivity.
I believe you are missing your certificates.
You can generate them using the InstallCerts app. (http://miteff.com/install-cert)
or http://opentox.ntua.gr/blog/77-ssl-certificates
Once you get your certificate, you need to put it under your security directory within your jdk home, for example:
C:\Program Files\Java\jdk1.6.0_45\jre\lib\security
Hope this resolves your issue
I have a trivial secure socket server-client program.
For the server certificates, I created a keystore using keytool.
When I try to connect to the server by my client I get these exceptions:
In server:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
In client:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
If my understanding is correct, these exceptions are caused due to the fact, that I am using certificates I created.
My question is the following:
If I set in the enabled cipher suites, both in server and in client, all the *_anon* cipher suites, shouldn't this solved the problem?
I mean If I enable the *_anon_* cipher suites then no authentication would be needed hence no exceptions.
Is this correct?
Because I still get exceptions. I tried having in the enabled cipher suites all the enabled+the _anon ones. No success. I tried setting only the anon ones and got a new exception:
Exception in thread "main" java.lang.IllegalArgumentException: Name must not be null
Could someone please explain why I get these exceptions, with the anon cipher suites?
Note:
If I set on the client the system property javax.net.ssl.trustStore pointing to the keystore I created and being used by my server, the communication is fine!
The program works with no exceptions and the data are send ok, from client to server.
UPDATE:
This is the snippet I use to enable the anon ciphers (I have done this for server and client part):
String[] supported = server.getSupportedCipherSuites();
String[] anonCipherSuitesSupported = new String[supported.length];
int count = 0;
for(int i = 0; i < supported.length; i++)
{
if(supported[i].indexOf("_anon_") > 0)
{
anonCipherSuitesSupported[count++] = supported[i];
}
}
String[] oldEnabled = server.getEnabledCipherSuites();
String[] newEnabled = new String[oldEnabled.length + count];
System.arraycopy(oldEnabled, 0, newEnabled, 0, oldEnabled.length);
System.arraycopy(anonCipherSuitesSupported, 0, newEnabled, oldEnabled.length, count);
server.setEnabledCipherSuites(newEnabled);
The stack trace is on client side:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(Unknown Source)
at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)
at sun.nio.cs.StreamEncoder.flush(Unknown Source)
at java.io.OutputStreamWriter.flush(Unknown Source)
at com.client.SSLClient1.main(SSLClient1.java:58)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
at sun.security.validator.Validator.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
... 14 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
at java.security.cert.CertPathBuilder.build(Unknown Source)
... 20 more
and on server side:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(Unknown Source)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(Unknown Source)
at com.server.SecureOrderTaker.main(SecureOrderTaker.java:92)
Now if I simply do:
server.setEnabledCipherSuites(anonCipherSuitesSupported);
So that only the anon cipher suites are enabled I get:
Exception in thread "main" java.lang.IllegalArgumentException: Name must not be null
at com.sun.net.ssl.internal.ssl.CipherSuite.valueOf(Unknown Source)
at com.sun.net.ssl.internal.ssl.CipherSuiteList.<init>(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLServerSocketImpl.setEnabledCipherSuites(Unknown Source)
at com.server.SecureOrderTaker.main(SecureOrderTaker.java:82)
Thank you
You are right, *_anon_* ciphers are used for a complete unauthenticated connection (both server and client are anonymous). With these cipher suites no certificate is required. I wrote a small code to test:
ServerSocketFactory sf = SSLServerSocketFactory.getDefault();
final SSLServerSocket socket = (SSLServerSocket)sf.createServerSocket(443);
System.out.println(Arrays.toString(socket.getSupportedCipherSuites()));
System.out.println(Arrays.toString(socket.getEnabledCipherSuites()));
socket.setEnabledCipherSuites(new String[] {"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"});
Thread t = new Thread() {
public void run() {
try {
Socket client = socket.accept();
client.getOutputStream().write("Hello World\n".getBytes("ASCII"));
client.close();
} catch (IOException ioe) {
}
}
};
t.start();
Thread.sleep(2000);
SSLSocket client = (SSLSocket) SSLSocketFactory.getDefault().createSocket("localhost", 443);
client.setEnabledCipherSuites(new String[] {"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA"});
InputStream in = client.getInputStream();
byte[] data = new byte[1024];
int len = in.read(data);
System.out.println(new String(data, 0, len));
I know that this code is not perfect but I successfully exchange data between the client and the server. Maybe your server or client socket is not well configured. Can you give the full stacktrace you got?
Note that these ciphers are deprecated since there are vulnerable to man-in-the-middle attacks.
UPDATE : I found the issue. The anonCipherSuitesSupported array length is too long. Therefore after adding the *_anon_* the array is ending with a bunch of null values. And the implementation does not seem to accept null in the enabled cipher list.
String[] supported = server.getSupportedCipherSuites();
List<String> list= new ArrayList<String>();
for(int i = 0; i < supported.length; i++)
{
if(supported[i].indexOf("_anon_") > 0)
{
list.add(supported[i]);
}
}
String[] anonCipherSuitesSupported = list.toArray(new String[0]);
You're dealing with certificates created by you, meaning you are the Certification Authority.
Your problem is that in order for both sides to shake hands and communicate, they need to both trust each others' certificates. Trust is established by building the chain from the certificate up to the CA to see if the specific side trusts that CA (some additional steps such as checking whether the certificate hasn't been revoked might be in place as well). Most major CAs are trusted by default in Java. In your case, your custom CA is not.
That means that your server certificate should be in the trust store of your client (as you mentioned, pointing it solves the problem). That, or the CA's certificate (better choice).
Take a look here for general details on SSL/TLS.
If you're dealing with mutual trust then your server should trust the CA that issued your client certificate as well.