package play.api.libs.ws.ssl.debug
import java.security.AccessController
import scala.util.control.NonFatal
import sun.security.util.Debug
object FixCertpathDebugLogging {
val logger = org.slf4j.LoggerFactory.getLogger("play.api.libs.ws.ssl.debug.FixCertpathDebugLogging")
class MonkeyPatchSunSecurityUtilDebugAction(val newDebug: Debug, val newOptions: String) extends FixLoggingAction {
val logger = org.slf4j.LoggerFactory.getLogger("play.api.libs.ws.ssl.debug.FixCertpathDebugLogging.MonkeyPatchSunSecurityUtilDebugAction")
val initialResource = "/sun/security/provider/certpath/Builder.class"
val debugType = classOf[Debug]
def isValidClass(className: String): Boolean = {
if (className.startsWith("java.security.cert")) return true
if (className.startsWith("sun.security.provider.certpath")) return true
if (className.equals("sun.security.x509.InhibitAnyPolicyExtension")) return true
false
}
def isUsingDebug: Boolean = (newOptions != null) && newOptions.contains("certpath")
def run() {
System.setProperty("java.security.debug", newOptions)
logger.debug(s"run: debugType = $debugType")
val debugValue = if (isUsingDebug) newDebug else null
var isPatched = false
for (
debugClass <- findClasses;
debugField <- debugClass.getDeclaredFields
) {
if (isValidField(debugField, debugType)) {
logger.debug(s"run: Patching $debugClass with $debugValue")
monkeyPatchField(debugField, debugValue)
isPatched = true
}
}
if (!isPatched) {
throw new IllegalStateException("No debug classes found!")
}
val argsField = debugType.getDeclaredField("args")
monkeyPatchField(argsField, newOptions)
}
}
class SunSecurityUtilDebugLogger(logger: org.slf4j.Logger) extends sun.security.util.Debug {
override def println(message: String) {
if (logger.isDebugEnabled) {
logger.debug(message)
}
}
override def println() {
if (logger.isDebugEnabled) {
logger.debug("")
}
}
}
def apply(newOptions: String, debugOption: Option[Debug] = None) {
logger.trace(s"apply: newOptions = $newOptions, debugOption = $debugOption")
try {
val newDebug = debugOption match {
case Some(d) => d
case None => new Debug()
}
val action = new MonkeyPatchSunSecurityUtilDebugAction(newDebug, newOptions)
AccessController.doPrivileged(action)
} catch {
case NonFatal(e) =>
throw new IllegalStateException("CertificateDebug configuration error", e)
}
}
}