alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Play Framework/Scala example source code file (DefaultHostnameVerifier.scala)

This example Play Framework source code file (DefaultHostnameVerifier.scala) is included in my "Source Code Warehouse" project. The intent of this project is to help you more easily find Play Framework (and Scala) source code examples by using tags.

All credit for the original source code belongs to Play Framework; I'm just trying to make examples easier to find. (For my Scala work, see my Scala examples and tutorials.)

Play Framework tags/keywords

api, boolean, can't, defaulthostnameverifier, hostnamechecker, hostnameverifier, kerberos, lib, library, play framework, principal, sslpeerunverifiedexception, string, web service, ws, x509certificate

The DefaultHostnameVerifier.scala Play Framework example source code

/*
 *
 *  * Copyright (C) 2009-2013 Typesafe Inc. <http://www.typesafe.com>
 *
 */
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

/**
 * Use the internal sun hostname checker as the hostname verifier.  Thanks to Kevin Locke.
 *
 * @see sun.security.util.HostnameChecker
 * @see http://kevinlocke.name/bits/2012/10/03/ssl-certificate-verification-in-dispatch-and-asynchttpclient/
 */
class DefaultHostnameVerifier extends HostnameVerifier {

  // AsyncHttpClient issue #197: "SSL host name verification disabled by default"
  // https://github.com/AsyncHttpClient/async-http-client/issues/197
  //
  // From http://docs.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#HostnameVerifier
  //
  // "When using raw SSLSockets/SSLEngines you should always check the peer's credentials before sending any data.
  // The SSLSocket and SSLEngine classes do not automatically verify that the hostname in a URL matches the
  // hostname in the peer's credentials. An application could be exploited with URL spoofing if the hostname is
  // not verified."
  //
  // We are using SSLEngine directly, so we have to use the AsyncHttpClient Netty Provider to provide hostnname
  // verification.

  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)
            // Certificate matches hostname
            true
          } catch {
            case e: CertificateException =>
              // Certificate does not match hostname
              val subjectAltNames = cert.getSubjectAlternativeNames
              logger.debug(s"verify: Certificate does not match hostname! subjectAltNames = $subjectAltNames, hostName = $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
  }

}

Other Play Framework source code examples

Here is a short list of links related to this Play Framework DefaultHostnameVerifier.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.