secure imap connection in java - java

I am trying to connect to our imap server listening on port 993 using a java program I found at :
http://harikrishnan83.wordpress.com/2009/01/24/access-gmail-with-imap-using-java-mail-api/
I am running this program on from Ubuntu.
However, I am getting below exception for this :
DEBUG: setDebug: JavaMail version 1.4ea
DEBUG: getProvider() returning javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Sun Microsystems, Inc]
DEBUG: mail.imap.fetchsize: 16384
javax.mail.MessagingException: Unrecognized SSL message, plaintext connection?;
nested exception is:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:479)
at javax.mail.Service.connect(Service.java:275)
at javax.mail.Service.connect(Service.java:156)
at org.myorg.IMAP.main(IMAP.java:40)
Caused by: javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at com.sun.net.ssl.internal.ssl.InputRecord.handleUnknownRecord(InputRecord.java:523)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:355)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:798)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:753)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)
at com.sun.mail.util.TraceInputStream.read(TraceInputStream.java:97)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
at com.sun.mail.iap.ResponseInputStream.read0(ResponseInputStream.java:81)
at com.sun.mail.iap.ResponseInputStream.readResponse(ResponseInputStream.java:67)
at com.sun.mail.iap.Response.<init>(Response.java:83)
at com.sun.mail.imap.protocol.IMAPResponse.<init>(IMAPResponse.java:48)
at com.sun.mail.imap.protocol.IMAPResponse.readResponse(IMAPResponse.java:122)
at com.sun.mail.imap.protocol.IMAPProtocol.readResponse(IMAPProtocol.java:230)
at com.sun.mail.iap.Protocol.<init>(Protocol.java:91)
at com.sun.mail.imap.protocol.IMAPProtocol.<init>(IMAPProtocol.java:87)
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:446)
... 3 more
At the end of this post they have suggested :
Looks like you have to add imap server’s certificate to your trusted cert store
Download imap server’s certificate
Locate your cacerts file
Use keytool to import the certificate to your cacerts file
However, I am not able to understand how to carry out these steps for an IMAP server running on Windows machine.
Could anybody pl. help me out here?

As the error message suggests, you are problably not connecting to a SSL encrypted port, but to a plaintext port. Please update your question with your actual configuration (host, port, protocol).
If you were missing the certificate, you would get a totally different error message.

Related

Default Mysql SSL connection faling after overriding default kaystore to custom keystore

I have Mysql 8.0.19 as docker instance.
In our application previously we use JDK's default keystore for SSL.
With JDK's keystore connection to Mysql server is just fine with SSL and without SSL.
Here we didnt configured the SSL for Mysql manually. We are using default SSL mechanism of Mysql.
Now for some reason we decided to use our own keystore and to use that we overrided the keystore for JVM with below variables
-Djavax.net.ssl.keyStore=$keystorePath$
-Djavax.net.ssl.keyStorePassword=$sslKeyStorePwd$
-Djavax.net.ssl.trustStore=$keystorePath$"
-Djavax.net.ssl.trustStorePassword=$sslKeyStorePwd$
Now after this, connection to mysql for SSL is faling with below errors
javax.net.ssl|ERROR|01|main|2021-08-10 16:20:30.019 IST|TransportContext.java:313|Fatal (UNKNOWN_CA): Received fatal alert: unknown_ca (
"throwable" : {
javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:128)
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:308)
at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:279)
Exception in thread "main" com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
In /var/lib/mysql/ we have
ca.pem,ca-key.pem,client-cert.pem,client-key.pem, public_key.pem,private_key.pem,server-cert.pem, server-key.pem.
To resolve this error I tried to import the ca.pem,client-cert.pem, server-cert.pem into our keystore but it didnt worked.
unknown_ca means that the certificate was not signed by a trusted Certificate Authority. My guess is that you do not have the whole chain in your keystore

LDAPS : Simple bind failed

I'm facing issue connecting to LDAPS from my application. I have imported all necessary certificates on JRE keystore.
I'm able to make calls to LDAPs when I put the following string in java.security
jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
When I change this line to
jdk.tls.disabledAlgorithms=MD5, DSA, DESede, DES_CBC, DHE, RC4, SSLv3, ECDH_anon, DH_anon, NULL, DH keySize < 768, RSA keySize < 2048
my connection fails with following error:
Caused by: javax.naming.CommunicationException: simple bind failed: testxxxxl.xxxx.com:636 [Root exception is java.net.SocketException: Socket closed]
at com.sun.jndi.ldap.LdapClient.authenticate(LdapClient.java:218)
at com.sun.jndi.ldap.LdapCtx.connect(LdapCtx.java:2740)
at com.sun.jndi.ldap.LdapCtx.<init>(LdapCtx.java:316)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURL(LdapCtxFactory.java:193)
at com.sun.jndi.ldap.LdapCtxFactory.getUsingURLs(LdapCtxFactory.java:211)
at com.sun.jndi.ldap.LdapCtxFactory.getLdapCtxInstance(LdapCtxFactory.java:154)
at com.sun.jndi.ldap.LdapCtxFactory.getInitialContext(LdapCtxFactory.java:84)
at org.jboss.as.naming.InitialContext.getDefaultInitCtx(InitialContext.java:122)
... 72 more
Caused by: java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:934)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:709)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at com.sun.jndi.ldap.Connection.writeRequest(Connection.java:431)
at com.sun.jndi.ldap.Connection.writeRequest(Connection.java:404)
at com.sun.jndi.ldap.LdapClient.ldapBind(LdapClient.java:358)
In wireshark it complains about certificate invalid.My question is if my certificate is invalid, it shouldn't be working with this line as well.
jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048
Please help me to solve the issue.
If you use a secure connection to the LDAP server and you see an error like the following when trying to connect to Active Directory:
simple bind failed: ad.hostname.com:636
Import the LDAP server public certificate directly into the Klocwork keystore (which should be_jvm\lib\security\cacerts).
This causes the certificate validation process at the Klocwork end to be bypassed, since you have decided to trust the LDAP server certificate by importing it into your list of trusted certificates.
Ask your LDAP administrator to set this extension of your LDAP server certificate to non-critical.
In recent versions of Java the TLSv1 has been disabled.
In my case this happened when upgrading from Java 8 to Java 11.
Re-enabling TLSv1 helped. It is as easy as defining property:
-Djdk.tls.client.protocols=TLSv1
Of course you can need also other protocols, so you can specify full list:
-Djdk.tls.client.protocols=TLSv1,TLSv1.1,TLSv1.2,TLSv1.3

Exception while connecting to mail server

I got the following exception while connecting to Mail server from IBM WAS.
javax.mail.MessagingException: Could not convert socket to TLS; nested exception is: java.net.SocketException: java.security.PrivilegedActionException: java.io.FileNotFoundException: D:\Program Files (x86)\IBM\WebSphere\AppServer\jre\lib\security\cacerts (The system cannot find the path specified.)
My question is:
What is the certificate that I should import? Is it the mail server's certificate which needs to be imported into WAS? Should I ask the mail server admin to share the certificate?
Once I figure out which certificate, I plan to follow these instructions to import it:
How to connect to a secure website using SSL in Java with a pkcs12 file?
That link is not the correct way to use mail sessions in WAS. Check this Websphere 7 javax.mail.MessagingException: SSLSocketFactory is null.
Try to use default SSL WebSphere configuration and Mail session resource. You will need to add your mail server certificate to the Trust store (NodeDeaultTrustStore or CellDefaultTrustStore depending whether you use standalone or network deployment version).
It should be possible to get mail server cert using a browser, when you connect using https://mailserver:port/ it should give you certificate which you could save locally and add to truststore. If you will have problems contact mail server admin.
PrivilegedActionException also suggest that you may have Java 2 security enabled. Check if it is enabled and if you really need it.

error while mailing from Java (SSLHandShake Exception)

I am getting following exception while sending mails from Java.
31/03 14:06:19:571 INFO [ ] IBSUtils sendMailfromsmtp() MessagingException in Sending Mail :javax.mail.MessagingException: Can't send command to SMTP host;
nested exception is:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: timestamp check failed
It's sending mails in stand alone java programs but while running from JBoss server its throwing this exception. Code has been working from six months but suddenly its starts throwing this exception.
Seems some certificate Expired.
I've ever get this kind of error when my application(IBM Java 1.6) handle connection with webserver(Oracle Java 1.6). There might be Handshake exception while negotiating SSH protocol.
You'd better set your Java protocol manually.
// Using IBM jre there will be a handshake failure as IBM java 1.6 will
// negotiate to server SSLv3 protocol while it SHOULD be TLSv1
System.setProperty("https.protocols", "TLSv1");
Seems some certificate Expired.
Correct. The server certificate has expired. Get it renewed, or complain to them if you can't get it done yourself.
Or else it hasn't come into its validity period yet.
Answering your request on how to get get information about the probably expired certificate:
Find out which server your mail is delivered to. Where this is configured depends on you utility class for sending mail, JEE style is to get it from a mail session configured in jboss.
Assuming you deliver your mail to somehost on port 25 you could use openssl s_client to perform a TLS handshake to get the certificate:
openssl s_client -starttls smtp -crlf -connect somehost:25
This gives you the certificate itself (the base64 encoded part between the "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE----- " delimiters and some basic information abobout it. Store the certificate including the delimiting lines in a file, say cert.pem.
You can then decode it using
openssl x509 -text -noout <cert.pem
This gives you all the information in the certificate as readable text.

Plaintext Connection

I am creating a simple HTTPS connection and returning a response
URL google = new URL("https://www.google.com/");
HttpsURLConnection connection = (HttpsURLConnection)google.openConnection();
System.out.println( "Response: " + connection.getResponseCode());
This works fine and I receive a 200 response (I have all the keystores and truststores etc. defined)
I then proxy the request through a Jetty server by using https.proxyPort=8443 and https.proxyHost-localhost
The server has connectors that look like this:
Server server = new Server();
SelectChannelConnector connector0 = new SelectChannelConnector();
connector0.setPort(8080);
SslSelectChannelConnector sslConnector = new SslSelectChannelConnector();
sslConnector.setPort(8443);
SslContextFactory cf = sslConnector.getSslContextFactory();
cf.setKeyStorePath(keyStoreHome);
cf.setKeyStorePassword(keyStorePassword);
cf.setTrustStore(trustStoreHome);
cf.setTrustStorePassword(trustStorePassword);
cf.setCertAlias("jetty");
server.setConnectors(new Connector[] {connector0, sslConnector});
server.setHandler(new HelloHandler());
server.start();
server.join();
Which gives me the error below:
DEBUG: org.eclipse.jetty.io.nio - created SCEP#33589e56{l(/127.0.0.1:62348)<->r(/127.0.0.1:8443),d=false,open=true,ishut=false,oshut=false,rb=false,wb=false,w=true,i=0}-{SslConnection#7f033a6f SSL NOT_HANDSHAKING i/o/u=-1/-1/-1 ishut=false oshut=false {AsyncHttpConnection#26c623af,g=HttpGenerator{s=0,h=-1,b=-1,c=-1},p=HttpParser{s=-14,l=0,c=0},r=0}}
DEBUG: org.eclipse.jetty.io.nio.ssl - [Session-1, SSL_NULL_WITH_NULL_NULL] SslConnection#7f033a6f SSL NOT_HANDSHAKING i/o/u=180/0/0 ishut=false oshut=false {AsyncHttpConnection#26c623af,g=HttpGenerator{s=0,h=-1,b=-1,c=-1},p=HttpParser{s=-14,l=0,c=0},r=0} NOT_HANDSHAKING filled=180/180 flushed=0/0
DEBUG: org.eclipse.jetty.io.nio.ssl - SCEP#33589e56{l(/127.0.0.1:62348)<->r(/127.0.0.1:8443),d=true,open=true,ishut=false,oshut=false,rb=false,wb=false,w=true,i=0r}-{SslConnection#7f033a6f SSL NEED_WRAP i/o/u=180/0/0 ishut=false oshut=false {AsyncHttpConnection#26c623af,g=HttpGenerator{s=0,h=-1,b=-1,c=-1},p=HttpParser{s=-14,l=0,c=0},r=0}}
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at com.sun.net.ssl.internal.ssl.EngineInputRecord.bytesInCompletePacket(EngineInputRecord.java:152)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:806)
at com.sun.net.ssl.internal.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:721)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:607)
at org.eclipse.jetty.io.nio.SslConnection.unwrap(SslConnection.java:519)
at org.eclipse.jetty.io.nio.SslConnection.process(SslConnection.java:354)
at org.eclipse.jetty.io.nio.SslConnection.access$900(SslConnection.java:43)
at org.eclipse.jetty.io.nio.SslConnection$SslEndPoint.fill(SslConnection.java:661)
at org.eclipse.jetty.http.HttpParser.fill(HttpParser.java:1030)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:275)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:230)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77)
at org.eclipse.jetty.io.nio.SslConnection.handle(SslConnection.java:191)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:620)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538)
at java.lang.Thread.run(Thread.java:662)
DEBUG: org.eclipse.jetty.io.nio.ChannelEndPoint - close SCEP#33589e56{l(/127.0.0.1:62348)<->r(/127.0.0.1:8443),d=true,open=true,ishut=false,oshut=false,rb=false,wb=false,w=true,i=0!}-{SslConnection#7f033a6f SSL NEED_WRAP i/o/u=180/0/0 ishut=false oshut=false {AsyncHttpConnection#26c623af,g=HttpGenerator{s=0,h=-1,b=-1,c=-1},p=HttpParser{s=-14,l=0,c=0},r=0}}
DEBUG: org.eclipse.jetty.http.HttpParser -
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
Can anybody please tell me what might be wrong with this?
By the looks of it the exception is occurring when the proxy is connecting the HTTP - 8080 and HTTPS - 8443. Does JETTY do decryption between those ports because if not the exception is about the 8080 being plain text.
This is more or less the same problem as in this question.
When you use https.proxyPort=8443 and https.proxyHost=localhost, the connection between your client and the proxy host/port isn't done using SSL/TLS, but in plain text HTTP. The client then sends the proxy a CONNECT request with the target host name (and this is way you get this "plain text" exception).
Then, the proxy makes a request to that target server and establishes a tunnel that relays all the raw traffic back and forth. From the client's point of view (HttpsUrlConnection), the socket that is connected to the proxy is upgraded to SSL/TLS (i.e. it initiate an handshake, which is relayed to the target server via that tunnel.
There aren't many clients that also support having the connection between the client and the proxy itself using HTTPS. This isn't generally very useful, since an attacker could only see the host name and port anyway.

Categories

Resources