To establish a SSL/TLS connection not vulnerable to man-in-the-middle attacks, it's essential to make sure the server presents the right certificate.
The certificate's hostname-specific data should match the server hostname.
It's not recommended to re-invent the wheel by implementing custom hostname verification.
TLS/SSL libraries provide built-in hostname verification functions that should be used.
This rule raises an issue when:
HostnameVerifier.verify()
method always return true
javax.mail.Session
is created with a Properties
object having no
mail.smtp.ssl.checkserveridentity
or mail.smtps.ssl.checkserveridentity
not configured to true
org.apache.commons.mail.SimpleEmail
is used with setSSLOnConnect(true)
or
setStartTLSEnabled(true)
or setStartTLSRequired(true)
without a call to setSSLCheckServerIdentity(true)
SSLContext sslcontext = SSLContext.getInstance( "TLS" ); sslcontext.init(null, new TrustManager[]{new X509TrustManager() { public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }}, new java.security.SecureRandom()); Client client = ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String requestedHost, SSLSession remoteServerSession) { return true; // Noncompliant } }).build();
SimpleEmail example:
Email email = new SimpleEmail(); email.setSmtpPort(465); email.setAuthenticator(new DefaultAuthenticator(username, password)); email.setSSLOnConnect(true); // Noncompliant; setSSLCheckServerIdentity(true) should also be called before sending the email email.send();
JavaMail's example:
Properties props = new Properties(); props.put("mail.smtp.host", "smtp.gmail.com"); props.put("mail.smtp.socketFactory.port", "465"); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); // Noncompliant; Session is created without having "mail.smtp.ssl.checkserveridentity" set to true props.put("mail.smtp.auth", "true"); props.put("mail.smtp.port", "465"); Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("username@gmail.com", "password"); } });
SSLContext sslcontext = SSLContext.getInstance( "TLSv1.2" ); sslcontext.init(null, new TrustManager[]{new X509TrustManager() { @Override public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} @Override public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {} @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } }}, new java.security.SecureRandom()); Client client = ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String requestedHost, SSLSession remoteServerSession) { return requestedHost.equalsIgnoreCase(remoteServerSession.getPeerHost()); // Compliant } }).build();
SimpleEmail example:
Email email = new SimpleEmail(); email.setSmtpPort(465); email.setAuthenticator(new DefaultAuthenticator(username, password)); email.setSSLOnConnect(true); email.setSSLCheckServerIdentity(true); // Compliant email.send();
JavaMail's example:
Properties props = new Properties(); props.put("mail.smtp.host", "smtp.gmail.com"); props.put("mail.smtp.socketFactory.port", "465"); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.port", "465"); props.put("mail.smtp.ssl.checkserveridentity", true); // Compliant Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("username@gmail.com", "password"); } });