[
https://issues.jboss.org/browse/JBIDE-19594?page=com.atlassian.jira.plugi...
]
Andre Dietisheim edited comment on JBIDE-19594 at 4/15/15 5:17 AM:
-------------------------------------------------------------------
An example of such a hostname verifier can be found in android land:
http://developer.android.com/reference/org/apache/http/conn/ssl/BrowserCo...
Another one can be found here:
https://tersesystems.com/2014/03/23/fixing-hostname-verification/
{code}
class DefaultHostnameVerifier extends HostnameVerifier {
private val logger = LoggerFactory.getLogger(getClass)
def hostnameChecker: HostnameChecker =
HostnameChecker.getInstance(HostnameChecker.TYPE_TLS)
def matchKerberos(hostname: String, principal: Principal) =
HostnameChecker.`match`(hostname, principal.asInstanceOf[KerberosPrincipal])
def isKerberos(principal: Principal): Boolean = principal != null &&
principal.isInstanceOf[KerberosPrincipal]
def verify(hostname: String, session: SSLSession): Boolean = {
logger.debug(s"verify: hostname = $hostname")
val checker = hostnameChecker
val result = try {
session.getPeerCertificates match {
case Array(cert: X509Certificate, _*) =>
try {
checker.`match`(hostname, cert)
// Certificate matches hostname
true
} catch {
case e: CertificateException =>
// Certificate does not match hostname
logger.debug("verify: Certificate does not match hostname", e)
false
}
case notMatch =>
// Peer does not have any certificates or they aren't X.509
logger.debug(s"verify: Peer does not have any certificates:
$notMatch")
false
}
} catch {
case _: SSLPeerUnverifiedException =>
// Not using certificates for verification, try verifying the principal
try {
val principal = session.getPeerPrincipal
if (isKerberos(principal)) {
matchKerberos(hostname, principal)
} else {
// Can't verify principal, not Kerberos
logger.debug(s"verify: Can't verify principal, not Kerberos")
false
}
} catch {
case e: SSLPeerUnverifiedException =>
// Can't verify principal, no principal
logger.debug("Can't verify principal, no principal", e)
false
}
}
logger.debug("verify: returning {}", result)
result
}
}
{code}
and here:
http://kevinlocke.name/bits/2012/10/03/ssl-certificate-verification-in-di...
{code}
/* An example program using AsyncHttpClient with SSL certificate verification
*
* To the extent possible under law, Kevin Locke has waived all copyright and
* related or neighboring rights to this work.
* A legal description of this waiver is available in LICENSE.txt.
*/
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.AsyncHttpClientConfig;
import com.ning.http.client.Response;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.ExecutionException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.security.auth.kerberos.KerberosPrincipal;
import sun.security.util.HostnameChecker;
/** Implements the "MyDownloader" application */
public class MyDownloader {
/** HostnameVerifier implementation which implements the same policy as the
* Java built-in pre-HostnameVerifier policy.
*/
private static class MyHostnameVerifier implements HostnameVerifier {
/** Checks if a given hostname matches the certificate or principal of
* a given session.
*/
private boolean hostnameMatches(String hostname, SSLSession session) {
HostnameChecker checker =
HostnameChecker.getInstance(HostnameChecker.TYPE_TLS);
boolean validCertificate = false, validPrincipal = false;
try {
Certificate[] peerCertificates = session.getPeerCertificates();
if (peerCertificates.length > 0 &&
peerCertificates[0] instanceof X509Certificate) {
X509Certificate peerCertificate =
(X509Certificate)peerCertificates[0];
try {
checker.match(hostname, peerCertificate);
// Certificate matches hostname
validCertificate = true;
} catch (CertificateException ex) {
// Certificate does not match hostname
}
} else {
// Peer does not have any certificates or they aren't X.509
}
} catch (SSLPeerUnverifiedException ex) {
// Not using certificates for peers, try verifying the principal
try {
Principal peerPrincipal = session.getPeerPrincipal();
if (peerPrincipal instanceof KerberosPrincipal) {
validPrincipal = HostnameChecker.match(hostname,
(KerberosPrincipal)peerPrincipal);
} else {
// Can't verify principal, not Kerberos
}
} catch (SSLPeerUnverifiedException ex2) {
// Can't verify principal, no principal
}
}
return validCertificate || validPrincipal;
}
public boolean verify(String hostname, SSLSession session) {
if (hostnameMatches(hostname, session)) {
return true;
} else {
// TODO: Add application-specific checks for
// hostname/certificate match
return false;
}
}
}
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: myhttp <URL>");
} else {
String url = args[0];
SSLContext context = null;
try {
context = SSLContext.getInstance("TLS");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return;
}
try {
context.init(null, null, null);
} catch (KeyManagementException e) {
e.printStackTrace();
return;
}
AsyncHttpClient client = new AsyncHttpClient(
new AsyncHttpClientConfig.Builder()
.setSSLContext(context)
.setHostnameVerifier(new MyHostnameVerifier())
.build()
);
Response response = null;
try {
response = client.prepareGet(url).execute().get();
} catch (InterruptedException e) {
e.printStackTrace();
return;
} catch (ExecutionException e) {
e.printStackTrace();
return;
} catch (IOException e) {
e.printStackTrace();
return;
}
if (response.getStatusCode() / 100 == 2) {
try {
String responseBody = response.getResponseBody();
System.err.println("Successfully downloaded " + url);
System.out.println(responseBody);
} catch (IOException e) {
e.printStackTrace();
return;
}
} else {
System.err.println("Failure downloading " + url +
": HTTP Status " + response.getStatusCode());
}
}
}
}
{code}
was (Author: adietish):
An example of such a hostname verifier can be found in android land:
http://developer.android.com/reference/org/apache/http/conn/ssl/BrowserCo...
Another one can be found here:
https://tersesystems.com/2014/03/23/fixing-hostname-verification/
{code}
class DefaultHostnameVerifier extends HostnameVerifier {
private val logger = LoggerFactory.getLogger(getClass)
def hostnameChecker: HostnameChecker =
HostnameChecker.getInstance(HostnameChecker.TYPE_TLS)
def matchKerberos(hostname: String, principal: Principal) =
HostnameChecker.`match`(hostname, principal.asInstanceOf[KerberosPrincipal])
def isKerberos(principal: Principal): Boolean = principal != null &&
principal.isInstanceOf[KerberosPrincipal]
def verify(hostname: String, session: SSLSession): Boolean = {
logger.debug(s"verify: hostname = $hostname")
val checker = hostnameChecker
val result = try {
session.getPeerCertificates match {
case Array(cert: X509Certificate, _*) =>
try {
checker.`match`(hostname, cert)
// Certificate matches hostname
true
} catch {
case e: CertificateException =>
// Certificate does not match hostname
logger.debug("verify: Certificate does not match hostname", e)
false
}
case notMatch =>
// Peer does not have any certificates or they aren't X.509
logger.debug(s"verify: Peer does not have any certificates:
$notMatch")
false
}
} catch {
case _: SSLPeerUnverifiedException =>
// Not using certificates for verification, try verifying the principal
try {
val principal = session.getPeerPrincipal
if (isKerberos(principal)) {
matchKerberos(hostname, principal)
} else {
// Can't verify principal, not Kerberos
logger.debug(s"verify: Can't verify principal, not Kerberos")
false
}
} catch {
case e: SSLPeerUnverifiedException =>
// Can't verify principal, no principal
logger.debug("Can't verify principal, no principal", e)
false
}
}
logger.debug("verify: returning {}", result)
result
}
}
{code}
SSL callback: provide meaningful hostname verifier, drop always
accepting hostnames
-----------------------------------------------------------------------------------
Key: JBIDE-19594
URL:
https://issues.jboss.org/browse/JBIDE-19594
Project: Tools (JBoss Tools)
Issue Type: Enhancement
Components: openshift
Affects Versions: 4.3.0.Alpha2
Reporter: Andre Dietisheim
Fix For: 4.3.0.Beta1
We're currently using an SSL callback that will allow users to get informed and act
upon "faulty" certificates (ex. self-signed ones) and mismatches btw. the host
we're talking to and the one that is referenced in the ssl certificate:
{code:title=com.openshift.client.IHttpClient.ISSLCertificateCallback}
public interface ISSLCertificateCallback {
public boolean allowCertificate(X509Certificate[] chain);
public boolean allowHostname(String hostname, SSLSession session);
}
{code}
The callback that we are using in JBT is presenting a dialog in case the jdk cannot
verify the certificate (ex. self signed certificates) and allows the user to accept/deny
it.
In case the jdk cannot verify the hostname (the host we're talking to is not matching
the host that's referenced in the certificate) we're currently always accepting
the hostname:
{code:title=org.jboss.tools.openshift.express.internal.ui.wizard.connection.SSLCertificateCallback}
@Override
public boolean allowHostname(String hostname, SSLSession sslSession) {
return true;
}
{code}
We should find a meaningfull implementation of such a verification that does not simply
always accept it. A first idea would be to present the mismatch to the user and allow it
to accept/refute it.
This issue came up JBIDE-19581 when there was no callback installed which made the
hostname verification failed as in jdk. The ssl certificate used by
--
This message was sent by Atlassian JIRA
(v6.3.11#6341)