package play.api.libs.ws.ssl
import java.security.cert.{ CertificateException, X509Certificate }
import javax.net.ssl.{ HostnameVerifier, SSLPeerUnverifiedException, SSLSession }
import javax.security.auth.kerberos.KerberosPrincipal
import sun.security.util.HostnameChecker
import org.slf4j.LoggerFactory
import com.ning.http.util.Base64
import java.security.Principal
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, sessionId (base64) = ${Base64.encode(session.getId)}")
val checker = hostnameChecker
val result = try {
session.getPeerCertificates match {
case Array(cert: X509Certificate, _*) =>
try {
checker.`match`(hostname, cert)
true
} catch {
case e: CertificateException =>
val subjectAltNames = cert.getSubjectAlternativeNames
logger.debug(s"verify: Certificate does not match hostname! subjectAltNames = $subjectAltNames, hostName = $hostname", e)
false
}
case notMatch =>
logger.debug(s"verify: Peer does not have any certificates: $notMatch")
false
}
} catch {
case _: SSLPeerUnverifiedException =>
try {
val principal = session.getPeerPrincipal
if (isKerberos(principal)) {
matchKerberos(hostname, principal)
} else {
logger.debug(s"verify: Can't verify principal, not Kerberos")
false
}
} catch {
case e: SSLPeerUnverifiedException =>
logger.debug("Can't verify principal, no principal", e)
false
}
}
logger.debug("verify: returning {}", result)
result
}
}